defmodule LivebookWeb.SessionLive.AppInfoComponent do use LivebookWeb, :live_component import LivebookWeb.AppHelpers alias Livebook.Notebook.AppSettings @impl true def mount(socket) do {:ok, assign(socket, deploy_confirmation: false)} end @impl true def update(assigns, socket) do changeset = case socket.assigns do %{changeset: changeset} when changeset.data == assigns.settings -> changeset _ -> AppSettings.change(assigns.settings) end {:ok, socket |> assign(assigns) |> assign(changeset: changeset)} end @impl true def render(assigns) do ~H"""

App settings

<.app_info_icon />
<%= if @deploy_confirmation do %>
Another app is already running under this slug, do you want to replace it?
<% else %> <.form :let={f} for={@changeset} phx-submit="deploy" phx-change="validate" phx-target={@myself} autocomplete="off" >
<.text_field field={f[:slug]} label="Slug" spellcheck="false" phx-debounce />
<.checkbox_field field={f[:access_type]} label="Password-protected" checked_value="protected" unchecked_value="public" /> <%= if Ecto.Changeset.get_field(@changeset, :access_type) == :protected do %> <.password_field field={f[:password]} spellcheck="false" phx-debounce /> <% end %>
<.checkbox_field field={f[:show_source]} label="Show source" />
<% end %>
<%= if @apps != [] do %>

Deployments

<.labeled_text label="Status"> <.app_status status={app.status} /> <.labeled_text label="URL" one_line> <%= if app.registered do %> <%= url(~p"/apps/#{app.settings.slug}") %> <% else %> - <% end %>
<.remix_icon icon="terminal-line" class="text-lg" /> <%= if app.registered do %> <% else %> <% end %>
<% end %>
""" end defp app_info_icon(assigns) do ~H""" <.remix_icon icon="question-line" class="text-xl leading-none" /> """ end @impl true def handle_event("validate", %{"_target" => ["reset"]}, socket) do settings = AppSettings.new() Livebook.Session.set_app_settings(socket.assigns.session.pid, settings) {:noreply, assign(socket, changeset: AppSettings.change(settings))} end def handle_event("validate", %{"app_settings" => params}, socket) do changeset = socket.assigns.settings |> AppSettings.change(params) |> Map.put(:action, :validate) with {:ok, settings} <- AppSettings.update(socket.assigns.settings, params) do Livebook.Session.set_app_settings(socket.assigns.session.pid, settings) end {:noreply, assign(socket, changeset: changeset)} end def handle_event("deploy", %{"app_settings" => params}, socket) do case AppSettings.update(socket.assigns.settings, params) do {:ok, settings} -> Livebook.Session.set_app_settings(socket.assigns.session.pid, settings) if slug_taken?(settings.slug, socket.assigns.apps) do {:noreply, assign(socket, deploy_confirmation: true)} else Livebook.Session.deploy_app(socket.assigns.session.pid) {:noreply, socket} end {:error, _changeset} -> {:noreply, socket} end end def handle_event("deploy_confirmation_confirm", %{}, socket) do Livebook.Session.deploy_app(socket.assigns.session.pid) {:noreply, assign(socket, deploy_confirmation: false)} end def handle_event("deploy_confirmation_cancel", %{}, socket) do {:noreply, assign(socket, deploy_confirmation: false)} end def handle_event("terminate_app", %{"session_id" => session_id}, socket) do app = Enum.find(socket.assigns.apps, &(&1.session_id == session_id)) Livebook.Session.close(app.session_pid) {:noreply, socket} end def handle_event("stop_app", %{"session_id" => session_id}, socket) do app = Enum.find(socket.assigns.apps, &(&1.session_id == session_id)) Livebook.Session.app_stop(app.session_pid) {:noreply, socket} end defp slug_taken?(slug, apps) do own? = Enum.any?(apps, fn app -> app.registered and app.settings.slug == slug end) not own? and Livebook.Apps.exists?(slug) end end