mirror of
https://github.com/livebook-dev/livebook.git
synced 2024-11-12 02:42:37 +08:00
c1654345b7
* Update phoenix deps
* Update reference to LiveDashboard encode_pid
* Fix form input id references
* Move to HEEx
* Update back to filesystem LV npm package
* Further HEEx rewrites
* Refactor icons into function components
* .html.leex -> .html.heex
* Further refactoring
* Move render helpers into function components
* Add doctype back
* Further refactoring
* Refactor cell component
* Further refactoring
* Compose sidebar using function components
* Rewrite notebook card component as function component
* Fruther refactoring
* Fix race condition in runtime tests
* Rewrite tooltips into function component
* Update Tailwind purge rules
* Revert "Rewrite tooltips into function component"
This reverts commit bd6ca8f0b5
.
* Refactor conditional tooltip
136 lines
3.9 KiB
Elixir
136 lines
3.9 KiB
Elixir
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
|
|
~H"""
|
|
<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">
|
|
<.choice_button
|
|
active={@path != nil}
|
|
phx-click="set_persistence_type"
|
|
phx-value-type="file"
|
|
phx-target={@myself}>
|
|
Save to file
|
|
</.choice_button>
|
|
<.choice_button
|
|
active={@path == nil}
|
|
phx-click="set_persistence_type"
|
|
phx-value-type="memory"
|
|
phx-target={@myself}>
|
|
Memory only
|
|
</.choice_button>
|
|
</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>
|
|
<button class="button button-blue mt-2"
|
|
phx-click="save"
|
|
phx-target={@myself}
|
|
disabled={disabled?(@path, @current_path, @running_paths)}>
|
|
Save
|
|
</button>
|
|
</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
|