Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A cancelled LiveView file upload appears to be re-added when adding a new file (or the same file) #3115

Closed
stuartjohnpage opened this issue Feb 13, 2024 · 1 comment · Fixed by #3133
Assignees

Comments

@stuartjohnpage
Copy link

stuartjohnpage commented Feb 13, 2024

Environment

  • Elixir version (elixir -v): 1.14.4 (I also tried with 15.6)
  • Phoenix version (mix deps): 1.7.10
  • Phoenix LiveView version (mix deps): 0.20.5
  • Operating system: OSX
  • Browsers you attempted to reproduce this bug on (the more the merrier): Brave, Chrome, Safari
  • Does the problem persist after removing "assets/node_modules" and trying again? Yes/no: Yes

Actual behavior

  • Add a file to upload
  • Cancel said file
  • Add a different file
  • Observe that different file is added
  • But also observe that the original file is added

I also recorded a video showing the issue if that doesn't make sense!

Screen.Recording.2024-02-13.at.11.21.48.AM.mov

Expected behavior

  • Add a file to upload
  • Cancel said file
  • Add a different file
  • Observe that only the new, different file, is added to be uploaded

Sample single file app to replicate

Application.put_env(:sample, Example.Endpoint,
  http: [ip: {127, 0, 0, 1}, port: 5001],
  server: true,
  live_view: [signing_salt: "aaaaaaaa"],
  secret_key_base: String.duplicate("a", 64),
  pubsub_server: Example.PubSub
)

Mix.install([
  {:plug_cowboy, "~> 2.5"},
  {:jason, "~> 1.0"},
  {:phoenix, "~> 1.7.10", override: true},
  {:phoenix_live_view, github: "phoenixframework/phoenix_live_view", branch: "main"}
])

defmodule Example.ErrorView do
  def render(template, _), do: Phoenix.Controller.status_message_from_template(template)
end

defmodule Example.HomeLive do
  use Phoenix.LiveView, layout: {__MODULE__, :live}

  @impl Phoenix.LiveView
  def mount(_params, _session, socket) do
    {:ok,
     socket
     |> assign(:uploaded_files, [])
     |> allow_upload(:avatar, accept: ~w(.jpg .jpeg), max_entries: 2)}
  end

  def render("live.html", assigns) do
    ~H"""
    <script src={"https://cdn.jsdelivr.net/npm/phoenix@1.7.10/priv/static/phoenix.min.js"}></script>
    <script src={"https://cdn.jsdelivr.net/npm/phoenix_live_view@0.20.5/priv/static/phoenix_live_view.min.js"}></script>
    <script>
      let liveSocket = new window.LiveView.LiveSocket("/live", window.Phoenix.Socket)
      liveSocket.connect()
    </script>
    <style>
      * { font-size: 1.1em; }
    </style>
    <%= @inner_content %>
    """
  end

  @impl Phoenix.LiveView
  def render(assigns) do
    ~H"""
    <form id="upload-form" phx-submit="save" phx-change="validate">
      <.live_file_input upload={@uploads.avatar} />
      <button type="submit">Upload</button>
    </form>

    <section phx-drop-target={@uploads.avatar.ref}>

    <%!-- render each avatar entry --%>
    <%= for entry <- @uploads.avatar.entries do %>
      <article class="upload-entry">
        <figure>
          <.live_img_preview entry={entry} />
          <figcaption><%= entry.client_name %></figcaption>
        </figure>
        <progress value={entry.progress} max="100"> <%= entry.progress %>% </progress>
        <button type="button" phx-click="cancel-upload" phx-value-ref={entry.ref} aria-label="cancel">&times;</button>
        <%= for err <- upload_errors(@uploads.avatar, entry) do %>
          <p class="alert alert-danger"><%= error_to_string(err) %></p>
        <% end %>
      </article>
    <% end %>

    <%= for err <- upload_errors(@uploads.avatar) do %>
      <p class="alert alert-danger"><%= error_to_string(err) %></p>
    <% end %>

    </section>
    """
  end

  @impl Phoenix.LiveView
  def handle_event("validate", _params, socket) do
    {:noreply, socket}
  end

  @impl Phoenix.LiveView
  def handle_event("cancel-upload", %{"ref" => ref}, socket) do
    {:noreply, cancel_upload(socket, :avatar, ref)}
  end

  @impl Phoenix.LiveView
  def handle_event("save", _params, socket) do
    uploaded_files =
      consume_uploaded_entries(socket, :avatar, fn %{path: path}, _entry ->
        # You will need to create `priv/static/uploads` for `File.cp!/2` to work.
        {:ok, path}
      end)

    {:noreply, update(socket, :uploaded_files, &(&1 ++ uploaded_files))}
  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"
end

defmodule Example.Router do
  use Phoenix.Router
  import Phoenix.LiveView.Router

  pipeline :browser do
    plug(:accepts, ["html"])
  end

  scope "/", Example do
    pipe_through(:browser)

    live("/", HomeLive, :index)
  end
end

defmodule Example.Endpoint do
  use Phoenix.Endpoint, otp_app: :sample
  socket("/live", Phoenix.LiveView.Socket)
  plug(Example.Router)
end

{:ok, _} =
  Supervisor.start_link([Example.Endpoint, {Phoenix.PubSub, name: Example.PubSub}],
    strategy: :one_for_one
  )

Process.sleep(:infinity)
@mjrusso
Copy link

mjrusso commented Feb 22, 2024

There have been some recent updates related to LiveView uploads in the changelog since this ticket was filed, but I'm able to confirm that I can still reproduce with LiveView 0.20.9, as well as the latest commit to main.

@SteffenDE SteffenDE self-assigned this Feb 22, 2024
SteffenDE added a commit to SteffenDE/phoenix_live_view that referenced this issue Feb 22, 2024
SteffenDE added a commit to SteffenDE/phoenix_live_view that referenced this issue Feb 22, 2024
SteffenDE added a commit to SteffenDE/phoenix_live_view that referenced this issue Feb 24, 2024
SteffenDE added a commit to SteffenDE/phoenix_live_view that referenced this issue Feb 24, 2024
SteffenDE added a commit to SteffenDE/phoenix_live_view that referenced this issue Feb 24, 2024
chrismccord pushed a commit that referenced this issue Feb 28, 2024
* Properly track preflighted uploads on the server

Fixes #3115.
Relates to #3004.
Partially fixes #2835.

* add test for #2965, #3115
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants