mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-10-10 21:46:46 +08:00
Add default directory setting (#2046)
Co-authored-by: Jonatan Kłosko <jonatanklosko@gmail.com>
This commit is contained in:
parent
c5138ad192
commit
72d18e5a38
7 changed files with 81 additions and 85 deletions
|
@ -4,6 +4,13 @@ defprotocol Livebook.FileSystem do
|
||||||
# This protocol defines an interface for file systems
|
# This protocol defines an interface for file systems
|
||||||
# that can be plugged into Livebook.
|
# that can be plugged into Livebook.
|
||||||
|
|
||||||
|
@typedoc """
|
||||||
|
An identifier uniquely identifying the given file system.
|
||||||
|
|
||||||
|
Every file system struct is expected have an `:id` field.
|
||||||
|
"""
|
||||||
|
@type id :: String.t()
|
||||||
|
|
||||||
@typedoc """
|
@typedoc """
|
||||||
A path uniquely idenfies file in the file system.
|
A path uniquely idenfies file in the file system.
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ defmodule Livebook.Migration do
|
||||||
move_app_secrets_to_personal_hub()
|
move_app_secrets_to_personal_hub()
|
||||||
add_personal_hub_secret_key()
|
add_personal_hub_secret_key()
|
||||||
update_file_systems_to_deterministic_ids()
|
update_file_systems_to_deterministic_ids()
|
||||||
|
move_default_file_system_id_to_default_dir()
|
||||||
end
|
end
|
||||||
|
|
||||||
defp delete_local_host_hub() do
|
defp delete_local_host_hub() do
|
||||||
|
@ -73,11 +74,10 @@ defmodule Livebook.Migration do
|
||||||
end
|
end
|
||||||
|
|
||||||
# Remap default file system id
|
# Remap default file system id
|
||||||
|
with {:ok, default_file_system_id} <-
|
||||||
default_file_system_id = Livebook.Settings.default_file_system_id()
|
Livebook.Storage.fetch_key(:settings, "global", :default_file_system_id),
|
||||||
|
{:ok, new_id} <- Map.fetch(id_mapping, default_file_system_id) do
|
||||||
if new_id = id_mapping[default_file_system_id] do
|
Livebook.Storage.insert(:settings, "global", default_file_system_id: new_id)
|
||||||
Livebook.Settings.set_default_file_system(new_id)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Livebook.NotebookManager is started before the migration runs,
|
# Livebook.NotebookManager is started before the migration runs,
|
||||||
|
@ -87,4 +87,20 @@ defmodule Livebook.Migration do
|
||||||
# notebooks at this point (and the user can easily star again)
|
# notebooks at this point (and the user can easily star again)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp move_default_file_system_id_to_default_dir() do
|
||||||
|
# Convert default_file_system_id to default_dir
|
||||||
|
# TODO: remove on Livebook v0.12
|
||||||
|
|
||||||
|
with {:ok, default_file_system_id} <-
|
||||||
|
Livebook.Storage.fetch_key(:settings, "global", :default_file_system_id) do
|
||||||
|
with {:ok, default_file_system} <-
|
||||||
|
Livebook.Settings.fetch_file_system(default_file_system_id) do
|
||||||
|
default_dir = Livebook.FileSystem.File.new(default_file_system)
|
||||||
|
Livebook.Settings.set_default_dir(default_dir)
|
||||||
|
end
|
||||||
|
|
||||||
|
Livebook.Storage.delete_key(:settings, "global", :default_file_system_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,11 +9,6 @@ defmodule Livebook.Settings do
|
||||||
alias Livebook.Storage
|
alias Livebook.Storage
|
||||||
alias Livebook.Settings.EnvVar
|
alias Livebook.Settings.EnvVar
|
||||||
|
|
||||||
@typedoc """
|
|
||||||
An id that is used for file system's manipulation, either insertion or removal.
|
|
||||||
"""
|
|
||||||
@type file_system_id :: String.t()
|
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Returns the current autosave path.
|
Returns the current autosave path.
|
||||||
"""
|
"""
|
||||||
|
@ -62,6 +57,22 @@ defmodule Livebook.Settings do
|
||||||
[Livebook.Config.local_file_system() | restored_file_systems]
|
[Livebook.Config.local_file_system() | restored_file_systems]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Finds a file system by id.
|
||||||
|
"""
|
||||||
|
@spec fetch_file_system(FileSystem.id()) :: {:ok, FileSystem.t()}
|
||||||
|
def fetch_file_system(file_system_id) do
|
||||||
|
local_file_system = Livebook.Config.local_file_system()
|
||||||
|
|
||||||
|
if file_system_id == local_file_system.id do
|
||||||
|
{:ok, local_file_system}
|
||||||
|
else
|
||||||
|
with {:ok, config} <- Storage.fetch(:file_systems, file_system_id) do
|
||||||
|
{:ok, storage_to_fs(config)}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Saves a new file system to the configured ones.
|
Saves a new file system to the configured ones.
|
||||||
"""
|
"""
|
||||||
|
@ -79,15 +90,15 @@ defmodule Livebook.Settings do
|
||||||
@doc """
|
@doc """
|
||||||
Removes the given file system from the configured ones.
|
Removes the given file system from the configured ones.
|
||||||
"""
|
"""
|
||||||
@spec remove_file_system(file_system_id()) :: :ok
|
@spec remove_file_system(FileSystem.id()) :: :ok
|
||||||
def remove_file_system(file_system_id) do
|
def remove_file_system(file_system_id) do
|
||||||
if default_file_system_id() == file_system_id do
|
if default_dir().file_system.id == file_system_id do
|
||||||
Livebook.Storage.delete_key(:settings, "global", :default_file_system_id)
|
Storage.delete_key(:settings, "global", :default_dir)
|
||||||
end
|
end
|
||||||
|
|
||||||
Livebook.NotebookManager.remove_file_system(file_system_id)
|
Livebook.NotebookManager.remove_file_system(file_system_id)
|
||||||
|
|
||||||
Livebook.Storage.delete(:file_systems, file_system_id)
|
Storage.delete(:file_systems, file_system_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp storage_to_fs(%{type: "s3"} = config) do
|
defp storage_to_fs(%{type: "s3"} = config) do
|
||||||
|
@ -222,38 +233,26 @@ defmodule Livebook.Settings do
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Sets default file system.
|
Sets default directory.
|
||||||
"""
|
"""
|
||||||
@spec set_default_file_system(file_system_id()) :: :ok
|
@spec set_default_dir(FileSystem.File.t()) :: :ok
|
||||||
def set_default_file_system(file_system_id) do
|
def set_default_dir(file) do
|
||||||
Livebook.Storage.insert(:settings, "global", default_file_system_id: file_system_id)
|
Storage.insert(:settings, "global",
|
||||||
|
default_dir: %{file_system_id: file.file_system.id, path: file.path}
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Returns the default file system.
|
Gets default directory.
|
||||||
"""
|
"""
|
||||||
@spec default_file_system() :: Filesystem.t()
|
@spec default_dir() :: FileSystem.File.t()
|
||||||
def default_file_system() do
|
def default_dir() do
|
||||||
case Livebook.Storage.fetch(:file_systems, default_file_system_id()) do
|
with {:ok, %{file_system_id: file_system_id, path: path}} <-
|
||||||
{:ok, file} -> storage_to_fs(file)
|
Storage.fetch_key(:settings, "global", :default_dir),
|
||||||
:error -> Livebook.Config.local_file_system()
|
{:ok, file_system} <- fetch_file_system(file_system_id) do
|
||||||
|
FileSystem.File.new(file_system, path)
|
||||||
|
else
|
||||||
|
_ -> FileSystem.File.new(Livebook.Config.local_file_system())
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
|
||||||
Returns the default file system id.
|
|
||||||
"""
|
|
||||||
@spec default_file_system_id() :: file_system_id()
|
|
||||||
def default_file_system_id() do
|
|
||||||
case Livebook.Storage.fetch_key(:settings, "global", :default_file_system_id) do
|
|
||||||
{:ok, default_file_system_id} -> default_file_system_id
|
|
||||||
:error -> "local"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Returns the home directory in the default file system.
|
|
||||||
"""
|
|
||||||
@spec default_file_system_home() :: FileSystem.File.t()
|
|
||||||
def default_file_system_home(), do: FileSystem.File.new(default_file_system())
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -121,6 +121,12 @@ defmodule LivebookWeb.FileSelectComponent do
|
||||||
<span>New notebook</span>
|
<span>New notebook</span>
|
||||||
</button>
|
</button>
|
||||||
</.menu_item>
|
</.menu_item>
|
||||||
|
<.menu_item>
|
||||||
|
<button role="menuitem" phx-click="set_default_directory" phx-target={@myself}>
|
||||||
|
<.remix_icon icon="home-6-line" />
|
||||||
|
<span>Use as default directory</span>
|
||||||
|
</button>
|
||||||
|
</.menu_item>
|
||||||
</.menu>
|
</.menu>
|
||||||
<div :if={@inner_block}>
|
<div :if={@inner_block}>
|
||||||
<%= render_slot(@inner_block) %>
|
<%= render_slot(@inner_block) %>
|
||||||
|
@ -560,6 +566,12 @@ defmodule LivebookWeb.FileSelectComponent do
|
||||||
{:noreply, assign(socket, error: false)}
|
{:noreply, assign(socket, error: false)}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def handle_event("set_default_directory", _params, socket) do
|
||||||
|
{dir, _prefix} = dir_and_prefix(socket.assigns.file)
|
||||||
|
Livebook.Settings.set_default_dir(dir)
|
||||||
|
{:noreply, socket}
|
||||||
|
end
|
||||||
|
|
||||||
defp update_file_infos(%{assigns: assigns} = socket, force_reload?) do
|
defp update_file_infos(%{assigns: assigns} = socket, force_reload?) do
|
||||||
current_file_infos = assigns[:file_infos] || []
|
current_file_infos = assigns[:file_infos] || []
|
||||||
{dir, prefix} = dir_and_prefix(assigns.file)
|
{dir, prefix} = dir_and_prefix(assigns.file)
|
||||||
|
|
|
@ -250,7 +250,7 @@ defmodule LivebookWeb.OpenLive do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp file_from_params(_params), do: Livebook.Settings.default_file_system_home()
|
defp file_from_params(_params), do: Livebook.Settings.default_dir()
|
||||||
|
|
||||||
defp import_source(socket, source, session_opts) do
|
defp import_source(socket, source, session_opts) do
|
||||||
{notebook, %{warnings: messages}} = Livebook.LiveMarkdown.notebook_from_livemd(source)
|
{notebook, %{warnings: messages}} = Livebook.LiveMarkdown.notebook_from_livemd(source)
|
||||||
|
|
|
@ -21,8 +21,7 @@ defmodule LivebookWeb.SettingsLive do
|
||||||
dialog_opened?: false
|
dialog_opened?: false
|
||||||
},
|
},
|
||||||
update_check_enabled: Livebook.UpdateCheck.enabled?(),
|
update_check_enabled: Livebook.UpdateCheck.enabled?(),
|
||||||
page_title: "Settings - Livebook",
|
page_title: "Settings - Livebook"
|
||||||
default_file_system_id: Livebook.Settings.default_file_system_id()
|
|
||||||
)}
|
)}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -110,10 +109,7 @@ defmodule LivebookWeb.SettingsLive do
|
||||||
is visible only to the current machine, but alternative file systems
|
is visible only to the current machine, but alternative file systems
|
||||||
are available, such as S3-based storages.
|
are available, such as S3-based storages.
|
||||||
</p>
|
</p>
|
||||||
<LivebookWeb.SettingsLive.FileSystemsComponent.render
|
<LivebookWeb.SettingsLive.FileSystemsComponent.render file_systems={@file_systems} />
|
||||||
file_systems={@file_systems}
|
|
||||||
default_file_system_id={@default_file_system_id}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<!-- Environment variables configuration -->
|
<!-- Environment variables configuration -->
|
||||||
<div class="flex flex-col space-y-4">
|
<div class="flex flex-col space-y-4">
|
||||||
|
@ -307,13 +303,8 @@ defmodule LivebookWeb.SettingsLive do
|
||||||
def handle_event("detach_file_system", %{"id" => file_system_id}, socket) do
|
def handle_event("detach_file_system", %{"id" => file_system_id}, socket) do
|
||||||
on_confirm = fn socket ->
|
on_confirm = fn socket ->
|
||||||
Livebook.Settings.remove_file_system(file_system_id)
|
Livebook.Settings.remove_file_system(file_system_id)
|
||||||
|
|
||||||
file_systems = Livebook.Settings.file_systems()
|
file_systems = Livebook.Settings.file_systems()
|
||||||
|
assign(socket, file_systems: file_systems)
|
||||||
assign(socket,
|
|
||||||
file_systems: file_systems,
|
|
||||||
default_file_system_id: Livebook.Settings.default_file_system_id()
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
{:noreply,
|
{:noreply,
|
||||||
|
@ -326,11 +317,6 @@ defmodule LivebookWeb.SettingsLive do
|
||||||
)}
|
)}
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_event("make_default_file_system", %{"id" => file_system_id}, socket) do
|
|
||||||
Livebook.Settings.set_default_file_system(file_system_id)
|
|
||||||
{:noreply, assign(socket, default_file_system_id: file_system_id)}
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_event("save", %{"update_check_enabled" => enabled}, socket) do
|
def handle_event("save", %{"update_check_enabled" => enabled}, socket) do
|
||||||
enabled = enabled == "true"
|
enabled = enabled == "true"
|
||||||
Livebook.UpdateCheck.set_enabled(enabled)
|
Livebook.UpdateCheck.set_enabled(enabled)
|
||||||
|
|
|
@ -15,10 +15,7 @@ defmodule LivebookWeb.SettingsLive.FileSystemsComponent do
|
||||||
<div class="flex items-center space-x-12">
|
<div class="flex items-center space-x-12">
|
||||||
<.file_system_info file_system={file_system} />
|
<.file_system_info file_system={file_system} />
|
||||||
</div>
|
</div>
|
||||||
<.file_system_actions
|
<.file_system_actions file_system_id={file_system.id} />
|
||||||
file_system_id={file_system.id}
|
|
||||||
default_file_system_id={@default_file_system_id}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
|
@ -46,33 +43,12 @@ defmodule LivebookWeb.SettingsLive.FileSystemsComponent do
|
||||||
defp file_system_actions(assigns) do
|
defp file_system_actions(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<div class="flex items-center space-x-2">
|
<div class="flex items-center space-x-2">
|
||||||
<span
|
<.menu :if={@file_system_id != "local"} id={"file-system-#{@file_system_id}-menu"}>
|
||||||
:if={@default_file_system_id == @file_system_id}
|
|
||||||
class="inline-flex items-center font-sans rounded-full px-2.5 py-0.5 text-xs font-medium bg-gray-100 bg-gray-100 text-gray-800"
|
|
||||||
>
|
|
||||||
Default
|
|
||||||
</span>
|
|
||||||
<.menu
|
|
||||||
:if={@default_file_system_id != @file_system_id or @file_system_id != "local"}
|
|
||||||
id={"file-system-#{@file_system_id}-menu"}
|
|
||||||
>
|
|
||||||
<:toggle>
|
<:toggle>
|
||||||
<button class="icon-button" aria-label="open file system menu" type="button">
|
<button class="icon-button" aria-label="open file system menu" type="button">
|
||||||
<.remix_icon icon="more-2-fill" class="text-xl" />
|
<.remix_icon icon="more-2-fill" class="text-xl" />
|
||||||
</button>
|
</button>
|
||||||
</:toggle>
|
</:toggle>
|
||||||
<.menu_item>
|
|
||||||
<button
|
|
||||||
:if={@default_file_system_id != @file_system_id}
|
|
||||||
type="button"
|
|
||||||
role="menuitem"
|
|
||||||
phx-click="make_default_file_system"
|
|
||||||
phx-value-id={@file_system_id}
|
|
||||||
>
|
|
||||||
<.remix_icon icon="star-line" />
|
|
||||||
<span>Make default</span>
|
|
||||||
</button>
|
|
||||||
</.menu_item>
|
|
||||||
<.menu_item variant={:danger}>
|
<.menu_item variant={:danger}>
|
||||||
<button
|
<button
|
||||||
:if={@file_system_id != "local"}
|
:if={@file_system_id != "local"}
|
||||||
|
|
Loading…
Add table
Reference in a new issue