defmodule LivebookWeb.AppsLive do
use LivebookWeb, :live_view
import LivebookWeb.AppHelpers
import LivebookWeb.SessionHelpers
alias LivebookWeb.LayoutHelpers
alias Livebook.Sessions
on_mount LivebookWeb.SidebarHook
@impl true
def mount(_params, _session, socket) do
if connected?(socket) do
Livebook.Sessions.subscribe()
end
sessions =
Sessions.list_sessions()
|> Enum.filter(&(&1.mode == :app))
|> Enum.sort_by(& &1.created_at, {:desc, DateTime})
{:ok, assign(socket, sessions: sessions, page_title: "Livebook - Apps")}
end
@impl true
def render(assigns) do
~H"""
<%= if @sessions == [] do %>
No apps currently running.
<% else %>
These apps are currently running.
<% end %>
<%= "/" <> slug %>
<%= for {session, idx} <- Enum.with_index(sessions) do %>
0} class="ml-4 border-l-2 border-gray-300 border-dashed h-6">
<.app_box session={session} />
<% end %>
"""
end
defp app_box(assigns) do
~H"""
<.labeled_text label="Status">
<.app_status status={@session.app_info.status} />
<.labeled_text label="Name">
<%= @session.notebook_name %>
"""
end
@impl true
def handle_info({type, session} = event, socket)
when type in [:session_created, :session_updated, :session_closed] and session.mode == :app do
{:noreply, update(socket, :sessions, &update_session_list(&1, event))}
end
def handle_info(_message, socket), do: {:noreply, socket}
@impl true
def handle_event("terminate_app", %{"session_id" => session_id}, socket) do
session = Enum.find(socket.assigns.sessions, &(&1.id == session_id))
Livebook.Session.close(session.pid)
{:noreply, socket}
end
def handle_event("stop_app", %{"session_id" => session_id}, socket) do
session = Enum.find(socket.assigns.sessions, &(&1.id == session_id))
Livebook.Session.app_stop(session.pid)
{:noreply, socket}
end
defp group_apps(sessions) do
sessions
|> Enum.group_by(& &1.app_info.slug)
|> Enum.sort_by(&elem(&1, 0))
end
end