Skip to content

Commit

Permalink
Merge branch 'phoenix-1.6-2022-refresh-issue-#89' of github.com:dwyl/…
Browse files Browse the repository at this point in the history
…app-mvp-phoenix into phoenix-1.6-2022-refresh-issue-#89
  • Loading branch information
nelsonic committed Jul 14, 2022
2 parents b563e64 + 91bded8 commit b35ca04
Show file tree
Hide file tree
Showing 15 changed files with 247 additions and 129 deletions.
16 changes: 16 additions & 0 deletions lib/app/ecto_atom.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
defmodule App.EctoAtom do
@moduledoc """
Custom Ecto type for atom
"""
use Ecto.Type

def type, do: :string

def cast(value) when is_atom(value), do: {:ok, value}
def cast(_), do: :error

def load(value), do: {:ok, String.to_atom(value)}

def dump(value) when is_atom(value), do: {:ok, Atom.to_string(value)}
def dump(_), do: :error
end
36 changes: 21 additions & 15 deletions lib/app/item.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@ defmodule App.Item do
alias __MODULE__

schema "items" do
field :person_id, :id
field :status_code, :integer
field :text, :string

belongs_to :status, App.Status, on_replace: :nilify
belongs_to :person, App.Person
timestamps()
end

@doc false
def changeset(item, attrs) do
item
|> cast(attrs, [:text, :person_id, :status_code])
|> validate_required([:text, :person_id])
|> cast(attrs, [:text])
|> validate_required([:text])
end

@doc """
Expand All @@ -32,9 +32,11 @@ defmodule App.Item do
{:error, %Ecto.Changeset{}}
"""
def create_item(attrs \\ %{}) do
def create_item(attrs \\ %{}, person, status) do
%Item{}
|> changeset(attrs)
|> put_assoc(:person, person)
|> put_assoc(:status, status)
|> Repo.insert()
end

Expand All @@ -52,10 +54,10 @@ defmodule App.Item do
** (Ecto.NoResultsError)
"""
def get_item!(id), do: Repo.get!(Item, id)
def get_item!(id), do: Repo.get!(Item, id) |> Repo.preload(:status)

@doc """
Returns the list of items.
Returns the list of items where the status is different to "deleted"
## Examples
Expand All @@ -64,10 +66,13 @@ defmodule App.Item do
"""
def list_items do
Item
|> order_by(desc: :inserted_at)
|> where([a], is_nil(a.status_code) or a.status_code != 6)
|> Repo.all()
query =
from i in Item,
join: s in assoc(i, :status),
where: s.text != :deleted,
preload: [status: s]

Repo.all(query)
end

@doc """
Expand All @@ -88,10 +93,11 @@ defmodule App.Item do
|> Repo.update()
end

# "soft" delete
def delete_item(id) do
get_item!(id)
|> Item.changeset(%{status_code: 6})
def update_status(%Item{} = item, status) do
item
|> Repo.preload(:status)
|> Ecto.Changeset.change()
|> put_assoc(:status, status)
|> Repo.update()
end
end
19 changes: 15 additions & 4 deletions lib/app/person.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,32 @@ defmodule App.Person do
field :key_id, :integer
field :locale, :string
field :picture, Fields.Encrypted
field :status_code, :integer

belongs_to :status, App.Status

timestamps()
end

@doc false
def changeset(person, attrs) do
person
|> cast(attrs, [:givenName, :auth_provider, :key_id, :picture, :locale, :status_code])
|> cast(attrs, [
:givenName,
:auth_provider,
:key_id,
:picture,
:locale
])
|> validate_required([:givenName, :auth_provider])
end
def create(attrs) do

def create(attrs, status) do
%Person{}
|> Repo.preload(:status)
|> changeset(attrs)
|> put_assoc(:status, status)
|> Repo.insert!()
end

def get_person!(id), do: Repo.get!(__MODULE__, id)
end
13 changes: 9 additions & 4 deletions lib/app/status.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,21 @@ defmodule App.Status do
alias __MODULE__

schema "status" do
field :text, :string
field :status_code, :integer
field :text, App.EctoAtom
field :code, :integer

has_many :items, App.Item
has_many :person, App.Person

timestamps()
end

@doc false
def changeset(status, attrs) do
status
|> cast(attrs, [:text, :status_code])
|> cast(attrs, [:text, :code])
|> validate_required([:text])
|> unique_constraint(:text)
end

def create(attrs) do
Expand All @@ -24,6 +28,8 @@ defmodule App.Status do
|> Repo.insert()
end

def get_by_text!(text), do: Repo.get_by!(__MODULE__, text: text)

def upsert(attrs) do
case Repo.get_by(__MODULE__, text: attrs.text) do
# create status
Expand All @@ -34,5 +40,4 @@ defmodule App.Status do
{:ok, status}
end
end

end
66 changes: 49 additions & 17 deletions lib/app_web/live/app_live.ex
Original file line number Diff line number Diff line change
@@ -1,39 +1,60 @@
defmodule AppWeb.AppLive do
use AppWeb, :live_view
alias App.{Item, Timer}
alias App.{Item, Person, Status, Timer}

@topic "live"

@impl true
def mount(_params, _session, socket) do
# subscribe to the channel
if connected?(socket), do: AppWeb.Endpoint.subscribe(@topic)
{:ok, assign(socket, items: Item.list_items(), editing: nil, timer: %Timer{})}

{:ok,
assign(socket, items: Item.list_items(), editing: nil, timer: %Timer{})}
end

@impl true
def handle_event("create", %{"text" => text}, socket) do
Item.create_item(%{text: text, person_id: 1, status_code: 2})
socket = assign(socket, items: Item.list_items(), active: %Item{}, timer: %Timer{})
person = Person.get_person!(1)
status = Status.get_by_text!(:uncategorized)
Item.create_item(%{text: text}, person, status)

socket =
assign(socket, items: Item.list_items(), active: %Item{}, timer: %Timer{})

AppWeb.Endpoint.broadcast_from(self(), @topic, "update", socket.assigns)
{:noreply, socket}
end

@impl true
def handle_event("toggle", data, socket) do
# Toggle the status of the item between 3 (:active) and 4 (:done)
status = if Map.has_key?(data, "value"), do: 4, else: 3
status =
if Map.has_key?(data, "value") do
Status.get_by_text!(:done)
else
Status.get_by_text!(:active)
end

item = Item.get_item!(Map.get(data, "id"))
Item.update_item(item, %{id: item.id, status_code: status})
socket = assign(socket, items: Item.list_items(), active: %Item{}, timer: %Timer{})
Item.update_status(item, status)

socket =
assign(socket, items: Item.list_items(), active: %Item{}, timer: %Timer{})

AppWeb.Endpoint.broadcast_from(self(), @topic, "update", socket.assigns)
{:noreply, socket}
end

@impl true
def handle_event("delete", data, socket) do
Item.delete_item(Map.get(data, "id"))
socket = assign(socket, items: Item.list_items(), active: %Item{}, timer: %Timer{})
def handle_event("delete", %{"id" => item_id}, socket) do
deleted_status = Status.get_by_text!(:deleted)
item = Item.get_item!(item_id)
Item.update_status(item, deleted_status)

socket =
assign(socket, items: Item.list_items(), active: %Item{}, timer: %Timer{})

AppWeb.Endpoint.broadcast_from(self(), @topic, "delete", socket.assigns)
{:noreply, socket}
end
Expand All @@ -44,10 +65,18 @@ defmodule AppWeb.AppLive do
# status = if Map.has_key?(data, "value"), do: 4, else: 3
item = Item.get_item!(Map.get(data, "id"))
# Item.update_item(item, %{id: item.id, status_code: status})
{:ok, timer} = Timer.start(%{item_id: item.id, person_id: 1, start: NaiveDateTime.utc_now})
{:ok, timer} =
Timer.start(%{
item_id: item.id,
person_id: 1,
start: NaiveDateTime.utc_now()
})

# IO.inspect(timer)

socket = assign(socket, items: Item.list_items(), active: %Item{}, timer: timer)
socket =
assign(socket, items: Item.list_items(), active: %Item{}, timer: timer)

AppWeb.Endpoint.broadcast_from(self(), @topic, "start|stop", socket.assigns)
{:noreply, socket}
end
Expand All @@ -64,13 +93,18 @@ defmodule AppWeb.AppLive do
{:ok, _timer} = Timer.stop(%{id: timer_id})
# IO.inspect(timer)

socket = assign(socket, items: Item.list_items(), active: %Item{}, timer: %Timer{})
socket =
assign(socket, items: Item.list_items(), active: %Item{}, timer: %Timer{})

AppWeb.Endpoint.broadcast_from(self(), @topic, "start|stop", socket.assigns)
{:noreply, socket}
end

@impl true
def handle_info(%{event: "start|stop", payload: %{items: items, timer: timer}}, socket) do
def handle_info(
%{event: "start|stop", payload: %{items: items, timer: timer}},
socket
) do
{:noreply, assign(socket, items: items, timer: timer)}
end

Expand All @@ -85,9 +119,7 @@ defmodule AppWeb.AppLive do
end

# helper function that checks for status 4 (:done)
def done?(item) do
not is_nil(item.status_code) and item.status_code == 4
end
def done?(item), do: item.status.text == :done

def started?(item, timer) do
# IO.inspect(item, label: "item")
Expand Down
4 changes: 2 additions & 2 deletions lib/app_web/live/app_live.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
</label>
<button class="bg-orange-600 text-white px-2 py-2 mr-2 mt-2 h-10"
phx-click="delete" phx-value-id={item.id}>
Delete
Delete!
</button>
<% else %>
<input type="checkbox" phx-value-id={item.id} phx-click="toggle"
Expand Down Expand Up @@ -108,4 +108,4 @@

return h + ':' + m + ':' + s;
}
</script>
</script>
6 changes: 4 additions & 2 deletions priv/repo/migrations/20220627162141_create_status.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ defmodule App.Repo.Migrations.CreateStatus do

def change do
create table(:status) do
add :text, :string
add :status_code, :integer
add(:text, :string)
add(:code, :integer)

timestamps()
end

create(unique_index(:status, [:text]))
end
end
14 changes: 6 additions & 8 deletions priv/repo/migrations/20220627162148_create_people.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,14 @@ defmodule App.Repo.Migrations.CreatePeople do

def change do
create table(:people) do
add :givenName, :binary
add :auth_provider, :string
add :key_id, :integer
add :picture, :binary
add :locale, :string
add :status_code, :integer
add(:givenName, :binary)
add(:auth_provider, :string)
add(:key_id, :integer)
add(:picture, :binary)
add(:locale, :string)
add(:status_id, references(:status, on_delete: :nothing))

timestamps()
end

create index(:people, [:status_code])
end
end
9 changes: 4 additions & 5 deletions priv/repo/migrations/20220627162154_create_items.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@ defmodule App.Repo.Migrations.CreateItems do

def change do
create table(:items) do
add :text, :string
add :person_id, references(:people, on_delete: :nothing)
add :status_code, :integer
add(:text, :string)
add(:person_id, references(:people, on_delete: :nothing))
add(:status_id, references(:status, on_delete: :nothing))

timestamps()
end

create index(:items, [:person_id])
create index(:items, [:status_code])
create(index(:items, [:person_id]))
end
end
Loading

0 comments on commit b35ca04

Please sign in to comment.