From ed22eb20f9f320d5ded4951c16fbb867b6883ce1 Mon Sep 17 00:00:00 2001 From: Logan Hunt Date: Wed, 6 Apr 2022 18:17:27 -0600 Subject: [PATCH] Add uploads; next up - user authentication on post --- config/dev.exs | 2 +- lib/aggiedit/rooms.ex | 35 +++++------------ lib/aggiedit/rooms/post.ex | 1 + lib/aggiedit/uploads/upload.ex | 5 +++ lib/aggiedit_web/endpoint.ex | 2 +- .../live/post_live/form_component.ex | 38 +++++++++++++++++-- .../live/post_live/form_component.html.heex | 10 +++++ lib/aggiedit_web/live/post_live/index.ex | 4 +- .../20220406184635_create_uploads.exs | 5 +-- 9 files changed, 66 insertions(+), 36 deletions(-) diff --git a/config/dev.exs b/config/dev.exs index 0e233c8..b90bee3 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -56,7 +56,7 @@ config :aggiedit, AggieditWeb.Endpoint, config :aggiedit, AggieditWeb.Endpoint, live_reload: [ patterns: [ - ~r"priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$", + ~r"priv/static/[^uploads].*(js|css|png|jpeg|jpg|gif|svg)$", ~r"priv/gettext/.*(po)$", ~r"lib/aggiedit_web/(live|views)/.*(ex)$", ~r"lib/aggiedit_web/templates/.*(eex)$" diff --git a/lib/aggiedit/rooms.ex b/lib/aggiedit/rooms.ex index fb10c4b..272f9b4 100644 --- a/lib/aggiedit/rooms.ex +++ b/lib/aggiedit/rooms.ex @@ -140,42 +140,25 @@ defmodule Aggiedit.Rooms do """ def get_post!(id), do: Repo.get!(Post, id) - @doc """ - Creates a post. - - ## Examples - - iex> create_post(%{field: value}) - {:ok, %Post{}} - - iex> create_post(%{field: bad_value}) - {:error, %Ecto.Changeset{}} - - """ - def create_post(attrs \\ %{}) do + def create_post(attrs, after_save \\ &{:ok, &1}) do %Post{} |> Post.changeset(attrs) |> Repo.insert() + |> post_saved(after_save) end - @doc """ - Updates a post. - - ## Examples - - iex> update_post(post, %{field: new_value}) - {:ok, %Post{}} - - iex> update_post(post, %{field: bad_value}) - {:error, %Ecto.Changeset{}} - - """ - def update_post(%Post{} = post, attrs) do + def update_post(%Post{} = post, attrs, after_save \\ &{:ok, &1}) do post |> Post.changeset(attrs) |> Repo.update() + |> post_saved(after_save) end + defp post_saved({:ok, post}, func) do + {:ok, _post} = func.(post) + end + defp post_saved(error, _fun), do: error + @doc """ Deletes a post. diff --git a/lib/aggiedit/rooms/post.ex b/lib/aggiedit/rooms/post.ex index ee9450d..2156fae 100644 --- a/lib/aggiedit/rooms/post.ex +++ b/lib/aggiedit/rooms/post.ex @@ -1,6 +1,7 @@ defmodule Aggiedit.Rooms.Post do use Ecto.Schema import Ecto.Changeset + alias Aggiedit.Repo schema "posts" do field :body, :string diff --git a/lib/aggiedit/uploads/upload.ex b/lib/aggiedit/uploads/upload.ex index f5f028d..ac3b8ad 100644 --- a/lib/aggiedit/uploads/upload.ex +++ b/lib/aggiedit/uploads/upload.ex @@ -18,4 +18,9 @@ defmodule Aggiedit.Uploads.Upload do |> cast(attrs, [:file, :mime, :size]) |> validate_required([:file, :mime, :size]) end + + def change_user(upload, user) do + change(upload) + |> put_assoc(:user, user) + end end diff --git a/lib/aggiedit_web/endpoint.ex b/lib/aggiedit_web/endpoint.ex index 47209ad..95577f0 100644 --- a/lib/aggiedit_web/endpoint.ex +++ b/lib/aggiedit_web/endpoint.ex @@ -20,7 +20,7 @@ defmodule AggieditWeb.Endpoint do at: "/", from: :aggiedit, gzip: false, - only: ~w(assets fonts images favicon.ico robots.txt) + only: ~w(assets fonts images favicon.ico robots.txt uploads) # Code reloading can be explicitly enabled under the # :code_reloader configuration of your endpoint. diff --git a/lib/aggiedit_web/live/post_live/form_component.ex b/lib/aggiedit_web/live/post_live/form_component.ex index 11ad4a1..53b19dd 100644 --- a/lib/aggiedit_web/live/post_live/form_component.ex +++ b/lib/aggiedit_web/live/post_live/form_component.ex @@ -2,6 +2,9 @@ defmodule AggieditWeb.PostLive.FormComponent do use AggieditWeb, :live_component alias Aggiedit.Rooms + alias Aggiedit.Rooms.Post + alias Aggiedit.Uploads.Upload + alias Aggiedit.Repo @impl true def update(%{post: post} = assigns, socket) do @@ -10,7 +13,10 @@ defmodule AggieditWeb.PostLive.FormComponent do {:ok, socket |> assign(assigns) - |> assign(:changeset, changeset)} + |> assign(:changeset, changeset) + |> assign(:uploaded_files, []) + |> allow_upload(:upload, accept: ~w(.jpg .jpeg .png .gif), max_entries: 1) + } end @impl true @@ -24,11 +30,35 @@ defmodule AggieditWeb.PostLive.FormComponent do end def handle_event("save", %{"post" => post_params}, socket) do - save_post(socket, socket.assigns.action, post_params) + socket + |> save_post(socket.assigns.action, post_params) + end + + defp save_upload(socket, %Post{} = post) do + consume_uploaded_entries(socket, :upload, fn data, upload -> + [extension | _] = MIME.extensions(upload.client_type) + filename = "#{upload.uuid}-#{extension}" + upload = %Upload{ + file: filename, + size: upload.client_size, + mime: upload.client_type + } + + dest = Path.join("priv/static/uploads", filename) + File.cp!(data.path, dest) + + Repo.preload(post, :upload) + |> Post.change_upload(upload) + |> Repo.update + IO.puts(inspect(upload)) + + {:ok, upload} + end) + {:ok, post} end defp save_post(socket, :edit, post_params) do - case Rooms.update_post(socket.assigns.post, post_params) do + case Rooms.update_post(socket.assigns.post, post_params, &save_upload(socket, &1)) do {:ok, _post} -> {:noreply, socket @@ -41,7 +71,7 @@ defmodule AggieditWeb.PostLive.FormComponent do end defp save_post(socket, :new, post_params) do - case Rooms.create_post(post_params) do + case Rooms.create_post(post_params, &save_upload(socket, &1)) do {:ok, _post} -> {:noreply, socket diff --git a/lib/aggiedit_web/live/post_live/form_component.html.heex b/lib/aggiedit_web/live/post_live/form_component.html.heex index 682ec78..695a90a 100644 --- a/lib/aggiedit_web/live/post_live/form_component.html.heex +++ b/lib/aggiedit_web/live/post_live/form_component.html.heex @@ -16,6 +16,16 @@ <%= label f, :body %> <%= textarea f, :body %> <%= error_tag f, :body %> + + <%= live_file_input @uploads.upload %> + + <%= for upload <- @uploads.upload.entries do %> +
+
+ <%= live_img_preview upload, height: 80 %> +
+
+ <% end %>
<%= submit "Save", phx_disable_with: "Saving..." %> diff --git a/lib/aggiedit_web/live/post_live/index.ex b/lib/aggiedit_web/live/post_live/index.ex index 1bf7bc3..1952625 100644 --- a/lib/aggiedit_web/live/post_live/index.ex +++ b/lib/aggiedit_web/live/post_live/index.ex @@ -3,6 +3,7 @@ defmodule AggieditWeb.PostLive.Index do alias Aggiedit.Rooms alias Aggiedit.Rooms.Post + alias Aggiedit.Repo @impl true def mount(_params, session, socket) do @@ -25,9 +26,10 @@ defmodule AggieditWeb.PostLive.Index do end defp apply_action(socket, :new, _params) do + post = %Post{user_id: socket.assigns[:current_user].id} socket |> assign(:page_title, "New Post") - |> assign(:post, %Post{}) + |> assign(:post, post) end defp apply_action(socket, :index, _params) do diff --git a/priv/repo/migrations/20220406184635_create_uploads.exs b/priv/repo/migrations/20220406184635_create_uploads.exs index 4b28397..8465ba6 100644 --- a/priv/repo/migrations/20220406184635_create_uploads.exs +++ b/priv/repo/migrations/20220406184635_create_uploads.exs @@ -6,11 +6,10 @@ defmodule Aggiedit.Repo.Migrations.CreateUploads do add :file, :text add :mime, :text add :size, :integer - add :user_id, references(:users, on_delete: :nothing) + + add :user_id, references(:users, on_delete: :delete_all) timestamps() end - - create index(:uploads, [:user_id]) end end