Packages
livebook
0.18.2
0.19.8
0.19.7
0.19.6
0.19.5
0.19.4
0.19.3
0.19.2
0.19.1
0.19.0
0.18.6
0.18.5
0.18.4
0.18.3
0.18.2
0.18.1
0.18.0
0.17.3
0.17.2
0.17.1
0.17.0
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.7
0.14.6
0.14.5
0.14.4
0.14.3
0.14.2
0.14.1
0.14.0
0.14.0-rc.1
0.14.0-rc.0
0.13.3
0.13.2
0.13.1
0.13.0
0.12.1
0.12.0
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.0
0.9.3
0.9.2
0.9.1
0.9.0
0.8.2
0.8.1
0.8.0
0.7.2
0.7.1
0.7.0
0.6.3
0.6.2
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
0.4.1
0.4.0
0.3.2
0.3.1
0.3.0
0.2.3
0.2.2
0.2.1
0.2.0
0.1.2
0.1.1
0.1.0
Automate code & data workflows with interactive notebooks
Current section
Files
Jump to
Current section
Files
lib/livebook_web/live/session_live/package_search_live.ex
defmodule LivebookWeb.SessionLive.PackageSearchLive do
use LivebookWeb, :live_view
@impl true
def mount(_params, %{"session_pid" => session_pid, "runtime" => runtime}, socket) do
socket =
assign(socket,
session: Livebook.Session.get_by_pid(session_pid),
runtime: runtime,
search: "",
search_ref: nil,
packages: [],
error_message: nil
)
socket = if connected?(socket), do: do_search(socket, ""), else: socket
{:ok, socket}
end
@impl true
def render(assigns) do
~H"""
<div class="flex flex-col space-y-5">
<h3 class="text-2xl font-semibold text-gray-800">
Search packages
</h3>
<p class="text-gray-700">
Find external packages for your notebook
</p>
<form phx-submit="submit" phx-change="search">
<.text_field
name="search"
value={@search}
phx-debounce="250"
placeholder="Search"
autocomplete="off"
spellcheck="false"
autofocus
/>
</form>
<div class={[
"flex flex-col divide-y h-[20rem] pr-2 -mr-2 overflow-y-auto tiny-scrollbar",
if(@search_ref, do: "opacity-30 transition-opacity duration-300")
]}>
<%= cond do %>
<% @error_message -> %>
<div class="error-box">
{@error_message}
</div>
<% @packages == [] -> %>
<div class="flex h-full items-center justify-center text-gray-600">
<.remix_icon icon="windy-line" class="text-xl" />
<div class="ml-2">No results</div>
</div>
<% true -> %>
<.package :for={{package, idx} <- Enum.with_index(@packages)} package={package} idx={idx} />
<% end %>
</div>
</div>
"""
end
defp package(assigns) do
~H"""
<div class="flex items-center">
<div class="flex-grow p-2 flex flex-col text-sm">
<div class="flex text-gray-700">
<%= if @package[:url] do %>
<a class="font-semibold" href={@package[:url]} target="_blank">{@package.name}</a>
<% else %>
<span class="font-semibold">{@package.name}</span>
<% end %>
<span class="ml-1">{@package.version}</span>
</div>
<div class="text-gray-600">
{@package.description}
</div>
</div>
<div class="ml-2">
<.button color="gray" small aria-label="add" phx-click={JS.push("add", value: %{idx: @idx})}>
<.remix_icon icon="add-line" />
<span>Add</span>
</.button>
</div>
</div>
"""
end
@impl true
def handle_event("search", %{"search" => search}, socket) do
{:noreply, do_search(socket, search)}
end
@impl true
def handle_event("submit", %{}, socket) do
socket =
case socket.assigns.packages do
[] -> socket
[first | _] -> add_dependency(socket, first.dependency)
end
{:noreply, socket}
end
@impl true
def handle_event("add", %{"idx" => idx}, socket) do
package = Enum.fetch!(socket.assigns.packages, idx)
socket = add_dependency(socket, package.dependency)
{:noreply, socket}
end
@impl true
def handle_info(
{:runtime_search_packages_response, ref, response},
%{assigns: %{search_ref: ref}} = socket
) do
socket =
case response do
{:ok, packages} ->
assign(socket, packages: packages, error_message: nil)
{:error, message} ->
assign(socket, error_message: Livebook.Utils.upcase_first(message))
end
{:noreply, assign(socket, search_ref: nil)}
end
def handle_info(_message, socket), do: {:noreply, socket}
defp do_search(socket, search) do
search_ref = Livebook.Runtime.search_packages(socket.assigns.runtime, self(), search)
assign(socket, search_ref: search_ref, search: search)
end
defp add_dependency(socket, dependency) do
Livebook.Session.add_dependencies(socket.assigns.session.pid, [dependency])
assign(socket, search: "", search_ref: nil, packages: [])
end
end