Compare commits

...

4 Commits

Author SHA1 Message Date
Ryan Rix 67a63e42c3 save/edit photos in ThingController actions 2020-09-16 21:12:19 -07:00
Ryan Rix d9a5bc9d0e add photo grid to show 2020-09-16 21:10:34 -07:00
Ryan Rix 37d66cd533 cleanup in PokaIjoWeb.Endpoint 2020-09-16 21:09:50 -07:00
Ryan Rix c7b783ce6c fix PokaIjo.Photo schema table reference 2020-09-16 21:09:39 -07:00
4 changed files with 41 additions and 16 deletions

View File

@ -11,9 +11,10 @@ The persistence model is a pretty simple Ecto model, it's got a single associati
#+begin_src elixir :noweb-ref ecto-schema-and-fns
use Ecto.Schema
use Arc.Ecto.Schema
use Arc.Ecto.Definition
import Ecto.Changeset
schema "photo" do
schema "photos" do
belongs_to :thing, PokaIjo.Thing
field :photo, PokaIjo.Photo.Type
field :uuid, :string
@ -24,8 +25,8 @@ end
def changeset(photo, attrs) do
photo
|> Map.update(:uuid, Ecto.UUID.generate, fn val -> val || Ecto.UUID.generate end)
|> cast(attrs, [:uuid])
|> cast_attachments(attrs, [:photo])
|> validate_required([:thing])
end
@doc "attach a photo to the provided Thing"

View File

@ -105,8 +105,8 @@ defmodule PokaIjoWeb.Endpoint do
<<plug-configurations>>
<<plug-session>>
<<Plug_Static>>
<<plug-uploads>>
<<Plug-Static>>
plug PokaIjoWeb.Router
end
@ -114,7 +114,7 @@ end
Serve at "/" the static files from "priv/static" directory. Since we will use =phx.digest= we can =gzip= the assets.
#+begin_src elixir :noweb-ref Plug_Static
#+begin_src elixir :noweb-ref Plug-Static
plug Plug.Static,
at: "/",
from: :poka_ijo,

View File

@ -131,6 +131,14 @@ end
<%= render_many @thing.contents, PokaIjoWeb.ThingView, "_card.html", conn: @conn %>
</div>
<% end %>
<%= if Enum.count(@thing.photos) > 0 do %>
<div class="grid-x small-up-2 medium-up-4">
<%= for img <- @thing.photos do %>
<%= img_tag PokaIjo.Photo.url({img.photo, img}, :thumb), class: "thumbnail cell" %>
<% end %>
</div>
<% end %>
</div>
<div class="small-12 medium-4 cell">
@ -186,7 +194,7 @@ end
#+begin_src elixir :noweb-ref controller-new
def new(conn, _params) do
changeset = Thing.new()
changeset = Thing.new(with_photo: true)
conn
|> put_view(PokaIjoWeb.ThingView)
@ -198,7 +206,7 @@ end
def insert(conn, %{"id" => id}) do
container = Thing.get_by(id: id)
changeset = Thing.new(%{"container_id" => container.id})
changeset = Thing.new(%{"container_id" => container.id}, with_photo: true)
conn
|> put_view(PokaIjoWeb.ThingView)
@ -230,7 +238,7 @@ end
<div class="callout warning">Warning: This does not have a parent object!</div>
<% end %>
<%= form_for @changeset, route_thing(@conn, @changeset, assigns[:thing]), fn f -> %>
<%= form_for @changeset, route_thing(@conn, @changeset, assigns[:thing]), [multipart: true], fn f -> %>
<%= if @changeset.action do %>
<div class="callout warning">Please check errors below!</div>
<% end %>
@ -259,6 +267,14 @@ end
value: <%= number_input f, :value_cents, step: 'any', value: @changeset.data.value_cents / 100 %>
<%= error_tag f, :value_cents %>
</label>
<%= inputs_for f, :photos, fn imf -> %>
<div class="form-group">
<%= label imf, :photo %>
<%= file_input imf, :photo %>
<%= error_tag imf, :photo %>
</div>
<% end %>
<%= submit "Submit", class: "button" %>
<% end %>
@ -308,7 +324,7 @@ def create(conn, params) do
|> Thing.new()
|> Thing.insert() do
{:error, changeset} ->
Logger.info("Changeset save failed: #{inspect(changeset.errors)}")
Logger.info("Changeset save failed: #{inspect(changeset)}")
conn
|> put_view(PokaIjoWeb.ThingView)
@ -330,7 +346,7 @@ some simple tests for =dollar_string_to_cents/1=; this would be great to have qu
#+begin_src elixir :tangle test/poka_ijo_web/controllers/thing_controller_test.exs
defmodule WebControllersThingDollarConvertorTest do
use PokaIjoWeb.ConnCase
alias PokaIjo.{Repo, Thing}
alias PokaIjo.{Repo, Thing, Photo}
alias PokaIjoWeb.ThingController
@ -434,7 +450,10 @@ end
#+begin_src elixir :noweb-ref controller-edit
def edit(conn, %{"id" => id}) do
thing = Thing.get_by(id: id, preload: true)
changeset = Thing.changeset(thing, %{})
changeset = cond do
Enum.count(thing.photos) > 0 -> Thing.changeset(thing, %{})
Enum.count(thing.photos) == 0 -> Thing.changeset(thing, %{photos: [%{}]})
end
conn
|> put_view(PokaIjoWeb.ThingView)
@ -454,7 +473,7 @@ def update(conn, %{"id" => id} = params) do
case Thing.update(changeset) do
{:error, changeset} ->
Logger.info("Changeset save failed: #{inspect(changeset.errors)}")
Logger.info("Changeset save failed: #{inspect(changeset)}")
conn
|> put_view(PokaIjoWeb.ThingView)
@ -701,7 +720,7 @@ defmodule PokaIjoWeb.ThingController do
use PokaIjoWeb, :controller
require Logger
alias PokaIjo.Thing
alias PokaIjo.{Repo, Photo, Thing}
<<controller-index>>
<<controller-show>>

View File

@ -7,7 +7,7 @@ This data model is pretty simple, Poka Ijo is made of Things. A =Thing= represen
defmodule PokaIjo.Thing do
use Ecto.Schema
require Logger
alias PokaIjo.{Thing, Repo}
alias PokaIjo.{Thing, Repo, Photo}
<<schema>>
@ -87,6 +87,10 @@ These functions aid in the creation and update of Things.
def new params do
Thing.changeset(%Thing{}, params)
end
def new params, with_photo: true do
Thing.changeset(%Thing{photos: [%Photo{}]})
end
def new do
new %{}
@ -95,13 +99,14 @@ These functions aid in the creation and update of Things.
- =PokaIjo.Thing.changeset/2= returns a changeset based on the thing in arg 1
#+begin_src elixir :noweb-ref thing-changeset
def changeset thing, params do
def changeset thing, params \\ %{} do
required_keys = [:name, :description]
all_keys = required_keys ++ [:container_id, :value_cents, :url]
thing
|> cast(params, all_keys)
|> cast_assoc(:container)
|> cast_assoc(:photos)
|> validate_required(required_keys)
|> validate_change(:container_id, fn :container_id, container_id ->
cond do
@ -145,7 +150,7 @@ I have some simple "getters" now:
end
def all(preload: true) do
all() |> Repo.preload([:container, :contents])
all() |> Repo.preload([:container, :contents, :photos])
end
#+end_src
@ -165,7 +170,7 @@ I have some simple "getters" now:
true ->
Repo.get_by(Thing, fparams)
|> Repo.preload([:contents, :container])
|> Repo.preload([:contents, :container, :photos])
end
end