Packages
livebook
0.11.4
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/notebook_cards_component.ex
defmodule LivebookWeb.NotebookCardsComponent do
use LivebookWeb, :live_component
@impl true
def render(assigns) do
assigns = assign_new(assigns, :card_icon, fn -> nil end)
~H"""
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-5" role="group">
<%= for {info, idx} <- Enum.with_index(@notebook_infos) do %>
<div
class="flex flex-col p-4 border bg-gray-50 border-gray-300 rounded-lg"
data-test-idx={idx}
>
<div class="flex items-center justify-between">
<span class="tooltip top" data-tooltip={info.file.path}>
<span class="text-gray-800 font-medium">
<%= info.name %>
</span>
</span>
<%= @card_icon && render_slot(@card_icon, {info, idx}) %>
</div>
<div class="mt-1 flex-grow text-gray-600 text-sm">
<%= @added_at_label %> <%= format_datetime_relatively(info.added_at) %> ago
</div>
<div class="mt-2 flex space-x-6">
<%= if session = session_by_file(info.file, @sessions) do %>
<.link navigate={~p"/sessions/#{session.id}"} class="text-blue-600 font-medium">
Join session
</.link>
<% else %>
<button
class="text-blue-600 font-medium"
phx-click={JS.push("open", value: %{idx: idx}, target: @myself)}
>
Open
</button>
<% end %>
<button
class="text-blue-600 font-medium"
phx-click={JS.push("fork", value: %{idx: idx}, target: @myself)}
>
Fork
</button>
</div>
</div>
<% end %>
</div>
"""
end
@impl true
def handle_event("open", %{"idx" => idx}, socket) do
%{file: file} = Enum.at(socket.assigns.notebook_infos, idx)
if file_running?(file, socket.assigns.sessions) do
session = session_by_file(file, socket.assigns.sessions)
{:noreply, push_navigate(socket, to: ~p"/sessions/#{session.id}")}
else
send(self(), {:open, file})
{:noreply, socket}
end
end
def handle_event("fork", %{"idx" => idx}, socket) do
%{file: file} = Enum.at(socket.assigns.notebook_infos, idx)
send(self(), {:fork, file})
{:noreply, socket}
end
defp file_running?(file, sessions) do
Enum.any?(sessions, &(&1.file == file))
end
defp session_by_file(file, sessions) do
Enum.find(sessions, &(&1.file == file))
end
end