2021-03-04 05:56:28 +08:00
|
|
|
defmodule LivebookWeb.SessionLive.PersistenceComponent do
|
|
|
|
use LivebookWeb, :live_component
|
2021-02-21 23:54:44 +08:00
|
|
|
|
2021-03-04 05:56:28 +08:00
|
|
|
alias Livebook.{Session, SessionSupervisor, LiveMarkdown}
|
2021-02-21 23:54:44 +08:00
|
|
|
|
|
|
|
@impl true
|
|
|
|
def mount(socket) do
|
|
|
|
session_summaries = SessionSupervisor.get_session_summaries()
|
2021-04-01 18:56:19 +08:00
|
|
|
running_paths = Enum.map(session_summaries, & &1.path)
|
|
|
|
{:ok, assign(socket, running_paths: running_paths)}
|
2021-02-21 23:54:44 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
@impl true
|
|
|
|
def render(assigns) do
|
|
|
|
~L"""
|
2021-04-28 20:28:28 +08:00
|
|
|
<div class="p-6 pb-4 flex flex-col space-y-3">
|
2021-04-22 05:02:09 +08:00
|
|
|
<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 %>
|
2021-02-21 23:54:44 +08:00
|
|
|
</div>
|
|
|
|
<%= if @path != nil do %>
|
2021-04-22 05:02:09 +08:00
|
|
|
<div class="h-full h-52">
|
2021-06-03 19:53:03 +08:00
|
|
|
<%= live_component LivebookWeb.PathSelectComponent,
|
2021-04-22 05:02:09 +08:00
|
|
|
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") %>
|
2021-02-21 23:54:44 +08:00
|
|
|
</div>
|
|
|
|
<% end %>
|
2021-04-22 05:02:09 +08:00
|
|
|
<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>
|
2021-03-24 00:46:33 +08:00
|
|
|
</div>
|
2021-02-21 23:54:44 +08:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
"""
|
|
|
|
end
|
|
|
|
|
|
|
|
@impl true
|
|
|
|
def handle_event("set_persistence_type", %{"type" => type}, socket) do
|
|
|
|
path =
|
|
|
|
case type do
|
2021-04-13 04:59:48 +08:00
|
|
|
"file" -> socket.assigns.current_path || default_path()
|
2021-02-21 23:54:44 +08:00
|
|
|
"memory" -> nil
|
|
|
|
end
|
|
|
|
|
|
|
|
{:noreply, assign(socket, path: path)}
|
|
|
|
end
|
|
|
|
|
|
|
|
def handle_event("set_path", %{"path" => path}, socket) do
|
|
|
|
{:noreply, assign(socket, path: path)}
|
|
|
|
end
|
|
|
|
|
2021-03-20 21:10:15 +08:00
|
|
|
def handle_event("save", %{}, socket) do
|
2021-02-21 23:54:44 +08:00
|
|
|
path = normalize_path(socket.assigns.path)
|
|
|
|
Session.set_path(socket.assigns.session_id, path)
|
2021-04-13 04:59:48 +08:00
|
|
|
Session.save_sync(socket.assigns.session_id)
|
2021-04-01 18:56:19 +08:00
|
|
|
|
|
|
|
running_paths =
|
|
|
|
if path do
|
|
|
|
[path | socket.assigns.running_paths]
|
|
|
|
else
|
|
|
|
List.delete(socket.assigns.running_paths, path)
|
|
|
|
end
|
|
|
|
|
2021-04-22 05:02:09 +08:00
|
|
|
# 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
|
|
|
|
)
|
|
|
|
|
2021-04-01 18:56:19 +08:00
|
|
|
{:noreply, assign(socket, running_paths: running_paths)}
|
2021-02-21 23:54:44 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
defp default_path() do
|
2021-04-15 20:51:27 +08:00
|
|
|
Livebook.Config.root_path() |> Path.join("notebook")
|
2021-02-21 23:54:44 +08:00
|
|
|
end
|
|
|
|
|
2021-04-01 18:56:19 +08:00
|
|
|
defp path_savable?(nil, _running_paths), do: true
|
2021-02-21 23:54:44 +08:00
|
|
|
|
2021-04-01 18:56:19 +08:00
|
|
|
defp path_savable?(path, running_paths) do
|
2021-02-21 23:54:44 +08:00
|
|
|
if File.exists?(path) do
|
|
|
|
File.regular?(path) and path not in running_paths
|
|
|
|
else
|
2021-04-01 18:56:19 +08:00
|
|
|
true
|
2021-02-21 23:54:44 +08:00
|
|
|
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
|
2021-04-13 04:59:48 +08:00
|
|
|
|
|
|
|
defp disabled?(path, current_path, running_paths) do
|
|
|
|
not path_savable?(normalize_path(path), running_paths) or normalize_path(path) == current_path
|
|
|
|
end
|
2021-02-21 23:54:44 +08:00
|
|
|
end
|