Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
defmodule BikeBrigadeWeb.CommunityFridgeLive.FormComponent do
use BikeBrigadeWeb, :live_component

alias BikeBrigade.Locations
alias BikeBrigade.{Locations, MediaStorage}

@impl true
def mount(socket) do
{:ok,
allow_upload(socket, :photo,
accept: ~w(.gif .png .jpg .jpeg),
max_entries: 1,
max_file_size: 10_000_000
)}
end

@impl true
def update(%{community_fridge: community_fridge} = assigns, socket) do
Expand All @@ -24,9 +34,35 @@ defmodule BikeBrigadeWeb.CommunityFridgeLive.FormComponent do
end

def handle_event("save", %{"community_fridge" => params}, socket) do
params =
case consume_uploaded_entries(socket, :photo, fn %{path: path},
%{client_type: content_type} ->
{:ok, MediaStorage.upload_file!(path, content_type)}
end) do
[%{url: url}] -> Map.put(params, "photo", url)
[] -> Map.update(params, "photo", nil, &if(&1 == "", do: nil, else: &1))
end

save_community_fridge(socket, socket.assigns.action, params)
end

def handle_event("delete_photo", _params, socket) do
changeset =
socket.assigns.community_fridge
|> Locations.change_community_fridge(%{photo: nil})
|> Map.put(:action, :validate)

{:noreply, assign(socket, :changeset, changeset)}
end

def handle_event("cancel_upload", %{"ref" => ref}, socket) do
{:noreply, cancel_upload(socket, :photo, ref)}
end

defp error_to_string(:too_large), do: "Too large"
defp error_to_string(:too_many_files), do: "You have selected too many files"
defp error_to_string(:not_accepted), do: "You have selected an unacceptable file type"

defp save_community_fridge(socket, :edit, params) do
case Locations.update_community_fridge(socket.assigns.community_fridge, params) do
{:ok, _community_fridge} ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,63 @@

<.input type="textarea" field={f[:description]} label="Description" />

<.input type="text" field={f[:photo]} label="Photo URL" />
<div>
<label class="block text-sm font-semibold leading-6 text-zinc-800">Photo</label>
<input
type="hidden"
name={Phoenix.HTML.Form.input_name(f, :photo)}
value={Phoenix.HTML.Form.input_value(f, :photo) || ""}
/>
<figure :if={Phoenix.HTML.Form.input_value(f, :photo) not in [nil, ""]} class="mt-2">
<img class="w-32 rounded" src={Phoenix.HTML.Form.input_value(f, :photo)} />
<figcaption class="flex mt-1">
<.button
color={:lightred}
size={:xsmall}
phx-click={JS.push("delete_photo", target: @myself)}
type="button"
>
Delete
</.button>
</figcaption>
</figure>
<div
class="flex justify-center px-6 py-10 mt-2 border border-dashed rounded-lg border-gray-900/25"
phx-drop-target={@uploads.photo.ref}
>
<div class="text-center">
<Heroicons.photo solid class="w-12 h-12 mx-auto text-gray-300" />
<div class="flex mt-4 text-sm leading-6 text-gray-600">
<label
for={@uploads.photo.ref}
class="relative font-semibold text-indigo-600 bg-white rounded-md cursor-pointer focus-within:outline-none focus-within:ring-2 focus-within:ring-indigo-600 focus-within:ring-offset-2 hover:text-indigo-500"
>
<span>Upload a file</span>
<.live_file_input upload={@uploads.photo} class="sr-only" />
</label>
<p class="pl-1">or drag and drop</p>
</div>
<p class="text-xs leading-5 text-gray-600">PNG, JPG, GIF up to 10MB</p>
</div>
</div>
<div class="mt-2">
<figure :for={entry <- @uploads.photo.entries} class="flex items-center gap-3 mt-2">
<.live_img_preview entry={entry} class="w-16 rounded" />
<div class="text-sm text-gray-600">{entry.client_name}</div>
<button
type="button"
phx-click={JS.push("cancel_upload", value: %{ref: entry.ref}, target: @myself)}
aria-label="cancel"
class="text-gray-400 hover:text-gray-600"
>
&times;
</button>
<p :for={err <- upload_errors(@uploads.photo, entry)} class="text-sm text-red-600">
{error_to_string(err)}
</p>
</figure>
</div>
</div>

<.input
type="checkbox"
Expand Down
57 changes: 56 additions & 1 deletion test/bike_brigade_web/live/community_fridge_live_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ defmodule BikeBrigadeWeb.CommunityFridgeLiveTest do
use BikeBrigadeWeb.ConnCase
import Phoenix.LiveViewTest

alias BikeBrigade.Locations
alias BikeBrigade.MediaStorage.FakeMediaStorage

describe "Community Fridges index (dispatcher)" do
setup [:login]
Expand Down Expand Up @@ -83,6 +83,61 @@ defmodule BikeBrigadeWeb.CommunityFridgeLiveTest do
end
end

describe "Community Fridge photo upload" do
setup [:login]

test "shows existing photo in edit form", ctx do
fridge =
fixture(:community_fridge, %{
name: "Photo Fridge",
photo: "https://example.com/fridge.jpg"
})

{:ok, _view, html} = live(ctx.conn, ~p"/community_fridges/#{fridge.id}/edit")

assert html =~ "https://example.com/fridge.jpg"
end

test "renders upload dropzone", ctx do
fixture(:community_fridge, %{name: "Upload Fridge"})
{:ok, view, _html} = live(ctx.conn, ~p"/community_fridges/new")

html = render(view)
assert html =~ "Upload a file"
assert html =~ "or drag and drop"
assert html =~ "PNG, JPG, GIF"
end

test "shows pending upload preview after file is selected", ctx do
{:ok, view, _html} = live(ctx.conn, ~p"/community_fridges/new")

upload =
file_input(view, "#community-fridge-form", :photo, [
%{name: "fridge.jpg", content: <<0, 1, 2>>, type: "image/jpeg"}
])

render_upload(upload, "fridge.jpg", 100)

html = render(view)
assert html =~ "fridge.jpg"
end

test "can cancel a pending upload", ctx do
{:ok, view, _html} = live(ctx.conn, ~p"/community_fridges/new")

upload =
file_input(view, "#community-fridge-form", :photo, [
%{name: "fridge.jpg", content: <<0, 1, 2>>, type: "image/jpeg"}
])

render_upload(upload, "fridge.jpg", 100)
assert render(view) =~ "fridge.jpg"

view |> element("button[aria-label='cancel']") |> render_click()
refute render(view) =~ "fridge.jpg"
end
end

describe "Community Fridges access control" do
setup [:login_as_rider]

Expand Down