defmodule LivebookWeb.SessionLive.CellUploadComponent do use LivebookWeb, :live_component alias Livebook.FileSystem @impl true def mount(socket) do {:ok, assign(socket, name: "", error_message: nil)} end @impl true def render(assigns) do ~H"""

Insert image

<%= if @uploads.cell_image.errors != [] do %>
Invalid image file. The image must be either GIF, JPEG, or PNG and cannot exceed 5MB in size.
<% end %> <%= if @error_message do %>
<%= @error_message %>
<% end %> <%= for entry <- @uploads.cell_image.entries do %>
<%= entry.client_name %> <%= entry.progress %>%
<% end %>
<%= live_patch("Cancel", to: @return_to, class: "button-base button-outlined-gray") %>
""" end @impl true def handle_event("validate", %{"name" => name}, socket) do {:noreply, assign(socket, name: name)} end def handle_event("save", %{"name" => name}, socket) do %{images_dir: images_dir} = socket.assigns.session consume_uploaded_entries(socket, :cell_image, fn %{path: path}, entry -> # Ensure the path is normalized (see https://github.com/elixir-plug/plug/issues/1047) # TODO: remove once we update to a Plug version with the issue resolved path = Path.expand(path) upload_file = FileSystem.File.local(path) ext = Path.extname(entry.client_name) filename = if name == "", do: entry.client_name, else: name <> ext destination_file = FileSystem.File.resolve(images_dir, filename) result = with :ok <- FileSystem.File.copy(upload_file, destination_file) do {:ok, filename} end {:ok, result} end) |> case do [{:ok, filename}] -> src_path = "images/#{URI.encode(filename, &URI.char_unreserved?/1)}" {:noreply, socket |> push_patch(to: socket.assigns.return_to) |> push_event("cell_upload", %{cell_id: socket.assigns.cell.id, url: src_path})} [{:error, message}] -> {:noreply, assign(socket, error_message: message)} end end end