mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-10-03 10:14:34 +08:00
Add support for importing notebook from URL query parameter (#598)
* Add support for importing notebook from URL query * Update desc * Update URL and redirect to import form on error * Update tests * Remove URL scope
This commit is contained in:
parent
06822b6e7e
commit
3ae67ede33
5 changed files with 89 additions and 10 deletions
|
@ -139,7 +139,8 @@ defmodule LivebookWeb.HomeLive do
|
|||
id: "import",
|
||||
modal_class: "w-full max-w-xl",
|
||||
return_to: Routes.home_path(@socket, :page),
|
||||
tab: @tab %>
|
||||
tab: @tab,
|
||||
import_opts: @import_opts %>
|
||||
<% end %>
|
||||
"""
|
||||
end
|
||||
|
@ -220,8 +221,23 @@ defmodule LivebookWeb.HomeLive do
|
|||
{:noreply, assign(socket, session: session)}
|
||||
end
|
||||
|
||||
def handle_params(%{"tab" => tab}, _url, socket) do
|
||||
{:noreply, assign(socket, tab: tab)}
|
||||
def handle_params(%{"tab" => tab} = params, _url, %{assigns: %{live_action: :import}} = socket) do
|
||||
import_opts = [url: params["url"]]
|
||||
{:noreply, assign(socket, tab: tab, import_opts: import_opts)}
|
||||
end
|
||||
|
||||
def handle_params(%{"url" => url}, _url, %{assigns: %{live_action: :public_import}} = socket) do
|
||||
url
|
||||
|> Livebook.ContentLoader.rewrite_url()
|
||||
|> Livebook.ContentLoader.fetch_content()
|
||||
|> case do
|
||||
{:ok, content} ->
|
||||
socket = import_content(socket, content, origin: {:url, url})
|
||||
{:noreply, socket}
|
||||
|
||||
{:error, _message} ->
|
||||
{:noreply, push_patch(socket, to: Routes.home_path(socket, :import, "url", url: url))}
|
||||
end
|
||||
end
|
||||
|
||||
def handle_params(_params, _url, socket), do: {:noreply, socket}
|
||||
|
@ -331,10 +347,8 @@ defmodule LivebookWeb.HomeLive do
|
|||
end
|
||||
|
||||
def handle_info({:import_content, content, session_opts}, socket) do
|
||||
{notebook, messages} = Livebook.LiveMarkdown.Import.notebook_from_markdown(content)
|
||||
socket = put_import_flash_messages(socket, messages)
|
||||
session_opts = Keyword.merge(session_opts, notebook: notebook)
|
||||
{:noreply, create_session(socket, session_opts)}
|
||||
socket = import_content(socket, content, session_opts)
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
def handle_info(
|
||||
|
@ -391,4 +405,11 @@ defmodule LivebookWeb.HomeLive do
|
|||
time_words = created_at |> DateTime.to_naive() |> Livebook.Utils.Time.time_ago_in_words()
|
||||
time_words <> " ago"
|
||||
end
|
||||
|
||||
defp import_content(socket, content, session_opts) do
|
||||
{notebook, messages} = Livebook.LiveMarkdown.Import.notebook_from_markdown(content)
|
||||
socket = put_import_flash_messages(socket, messages)
|
||||
session_opts = Keyword.merge(session_opts, notebook: notebook)
|
||||
create_session(socket, session_opts)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -27,7 +27,7 @@ defmodule LivebookWeb.HomeLive.ImportComponent do
|
|||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<%= live_component component_for_tab(@tab), id: "import-#{@tab}" %>
|
||||
<%= live_component component_for_tab(@tab), [{:id, "import-#{@tab}"} | @import_opts] %>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
|
|
|
@ -8,6 +8,15 @@ defmodule LivebookWeb.HomeLive.ImportUrlComponent do
|
|||
{:ok, assign(socket, url: "", error_message: nil)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def update(assigns, socket) do
|
||||
if url = assigns[:url] do
|
||||
{:ok, do_import(socket, url)}
|
||||
else
|
||||
{:ok, socket}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def render(assigns) do
|
||||
~H"""
|
||||
|
@ -45,16 +54,20 @@ defmodule LivebookWeb.HomeLive.ImportUrlComponent do
|
|||
end
|
||||
|
||||
def handle_event("import", %{"data" => %{"url" => url}}, socket) do
|
||||
{:noreply, do_import(socket, url)}
|
||||
end
|
||||
|
||||
defp do_import(socket, url) do
|
||||
url
|
||||
|> ContentLoader.rewrite_url()
|
||||
|> ContentLoader.fetch_content()
|
||||
|> case do
|
||||
{:ok, content} ->
|
||||
send(self(), {:import_content, content, [origin: {:url, url}]})
|
||||
{:noreply, socket}
|
||||
socket
|
||||
|
||||
{:error, message} ->
|
||||
{:noreply, assign(socket, error_message: Utils.upcase_first(message))}
|
||||
assign(socket, url: url, error_message: Utils.upcase_first(message))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -52,6 +52,13 @@ defmodule LivebookWeb.Router do
|
|||
home_app: {"Livebook", :livebook}
|
||||
end
|
||||
|
||||
# Public URLs that people may be directed to
|
||||
scope "/", LivebookWeb do
|
||||
pipe_through [:browser, :auth]
|
||||
|
||||
live "/import", HomeLive, :public_import
|
||||
end
|
||||
|
||||
scope "/", LivebookWeb do
|
||||
pipe_through :browser
|
||||
|
||||
|
|
|
@ -208,6 +208,44 @@ defmodule LivebookWeb.HomeLiveTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "public import endpoint" do
|
||||
test "imports notebook from the given url and redirects to the new session", %{conn: conn} do
|
||||
bypass = Bypass.open()
|
||||
|
||||
Bypass.expect_once(bypass, "GET", "/notebook", fn conn ->
|
||||
conn
|
||||
|> Plug.Conn.put_resp_content_type("text/plain")
|
||||
|> Plug.Conn.resp(200, "# My notebook")
|
||||
end)
|
||||
|
||||
notebook_url = "http://localhost:#{bypass.port}/notebook"
|
||||
|
||||
assert {:error, {:live_redirect, %{to: to}}} =
|
||||
live(conn, "/import?url=#{URI.encode_www_form(notebook_url)}")
|
||||
|
||||
{:ok, view, _} = live(conn, to)
|
||||
assert render(view) =~ "My notebook"
|
||||
end
|
||||
|
||||
test "redirects to the import form on error", %{conn: conn} do
|
||||
bypass = Bypass.open()
|
||||
|
||||
Bypass.expect(bypass, "GET", "/notebook", fn conn ->
|
||||
Plug.Conn.resp(conn, 500, "Error")
|
||||
end)
|
||||
|
||||
notebook_url = "http://localhost:#{bypass.port}/notebook"
|
||||
|
||||
assert {:error, {:live_redirect, %{to: to}}} =
|
||||
live(conn, "/import?url=#{URI.encode_www_form(notebook_url)}")
|
||||
|
||||
assert to == "/home/import/url?url=#{URI.encode_www_form(notebook_url)}"
|
||||
|
||||
{:ok, view, _} = live(conn, to)
|
||||
assert render(view) =~ notebook_url
|
||||
end
|
||||
end
|
||||
|
||||
# Helpers
|
||||
|
||||
defp test_notebook_path(name) do
|
||||
|
|
Loading…
Add table
Reference in a new issue