Packages
livebook
0.9.3
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" => session, "runtime" => runtime, "return_to" => return_to},
socket
) do
socket =
assign(socket,
session: session,
runtime: runtime,
return_to: return_to,
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="p-6 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">
<input
class="input"
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-75"}"
}>
<%= 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
class="button-base button-gray whitespace-nowrap py-1 px-2"
aria-label="add"
phx-click={JS.push("add", value: %{idx: @idx})}
>
<.remix_icon icon="add-line" class="align-middle mr-1 text-xs" />
<span class="font-normal text-xs">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])
push_patch(socket, to: socket.assigns.return_to)
end
end