Packages
livebook
0.2.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/persistence_component.ex
defmodule LivebookWeb.SessionLive.PersistenceComponent do
use LivebookWeb, :live_component
alias Livebook.{Session, SessionSupervisor, LiveMarkdown}
@impl true
def mount(socket) do
session_summaries = SessionSupervisor.get_session_summaries()
running_paths = Enum.map(session_summaries, & &1.path)
{:ok, assign(socket, running_paths: running_paths)}
end
@impl true
def render(assigns) do
~L"""
<div class="p-6 pb-4 flex flex-col space-y-3">
<h3 class="text-2xl font-semibold text-gray-800">
File
</h3>
<div class="w-full flex-col space-y-5">
<p class="text-gray-700">
Specify where the notebook should be automatically persisted.
</p>
<div class="flex space-x-4">
<%= content_tag :button, "Save to file",
class: "choice-button #{if(@path != nil, do: "active")}",
phx_click: "set_persistence_type",
phx_value_type: "file",
phx_target: @myself %>
<%= content_tag :button, "Memory only",
class: "choice-button #{if(@path == nil, do: "active")}",
phx_click: "set_persistence_type",
phx_value_type: "memory",
phx_target: @myself %>
</div>
<%= if @path != nil do %>
<div class="h-full h-52">
<%= live_component LivebookWeb.PathSelectComponent,
id: "path_select",
path: @path,
extnames: [LiveMarkdown.extension()],
running_paths: @running_paths,
phx_target: @myself,
phx_submit: if(disabled?(@path, @current_path, @running_paths), do: nil, else: "save") %>
</div>
<% end %>
<div class="flex flex-col space-y-2">
<%= if @path != nil do %>
<div class="text-gray-500 text-sm">
File: <%= normalize_path(@path) %>
</div>
<% end %>
<div>
<%= content_tag :button, "Save",
class: "button button-blue mt-2",
phx_click: "save",
phx_target: @myself,
disabled: disabled?(@path, @current_path, @running_paths) %>
</div>
</div>
</div>
</div>
"""
end
@impl true
def handle_event("set_persistence_type", %{"type" => type}, socket) do
path =
case type do
"file" -> socket.assigns.current_path || default_path()
"memory" -> nil
end
{:noreply, assign(socket, path: path)}
end
def handle_event("set_path", %{"path" => path}, socket) do
{:noreply, assign(socket, path: path)}
end
def handle_event("save", %{}, socket) do
path = normalize_path(socket.assigns.path)
Session.set_path(socket.assigns.session_id, path)
Session.save_sync(socket.assigns.session_id)
running_paths =
if path do
[path | socket.assigns.running_paths]
else
List.delete(socket.assigns.running_paths, path)
end
# After saving the file reload the directory contents,
# so that the new file gets shown.
send_update(LivebookWeb.PathSelectComponent,
id: "path_select",
running_paths: running_paths,
force_reload: true
)
{:noreply, assign(socket, running_paths: running_paths)}
end
defp default_path() do
Livebook.Config.root_path() |> Path.join("notebook")
end
defp path_savable?(nil, _running_paths), do: true
defp path_savable?(path, running_paths) do
if File.exists?(path) do
File.regular?(path) and path not in running_paths
else
true
end
end
defp normalize_path(nil), do: nil
defp normalize_path(path) do
if String.ends_with?(path, LiveMarkdown.extension()) do
path
else
path <> LiveMarkdown.extension()
end
end
defp disabled?(path, current_path, running_paths) do
not path_savable?(normalize_path(path), running_paths) or normalize_path(path) == current_path
end
end