diff --git a/assets/css/components.css b/assets/css/components.css
index a54d76a30..f03fe724c 100644
--- a/assets/css/components.css
+++ b/assets/css/components.css
@@ -70,7 +70,7 @@
/* Form fields */
.input {
- @apply w-full px-3 py-2 bg-gray-50 text-sm border border-gray-200 rounded-lg placeholder-gray-400 text-gray-600 phx-form-error:border-red-300;
+ @apply w-full px-3 py-2 bg-gray-50 text-sm border border-gray-200 rounded-lg placeholder-gray-400 text-gray-600 phx-form-error:border-red-300 disabled:opacity-70 disabled:cursor-not-allowed;
}
.input[type="color"] {
diff --git a/lib/livebook/hubs/dockerfile.ex b/lib/livebook/hubs/dockerfile.ex
index 241c6a329..1d77d7b53 100644
--- a/lib/livebook/hubs/dockerfile.ex
+++ b/lib/livebook/hubs/dockerfile.ex
@@ -14,20 +14,26 @@ defmodule Livebook.Hubs.Dockerfile do
}
@doc """
- Builds a changeset for app Dockerfile configuration.
+ Builds the default Dockerfile configuration.
"""
- @spec config_changeset(map()) :: Ecto.Changeset.t()
- def config_changeset(attrs \\ %{}) do
+ @spec config_new() :: config()
+ def config_new() do
default_image = Livebook.Config.docker_images() |> hd()
- data = %{
+ %{
deploy_all: false,
docker_tag: default_image.tag,
clustering: nil,
zta_provider: nil,
zta_key: nil
}
+ end
+ @doc """
+ Builds a changeset for app Dockerfile configuration.
+ """
+ @spec config_changeset(config(), map()) :: Ecto.Changeset.t()
+ def config_changeset(config, attrs \\ %{}) do
zta_types =
for provider <- Livebook.Config.identity_providers(),
do: provider.type
@@ -40,7 +46,7 @@ defmodule Livebook.Hubs.Dockerfile do
zta_key: :string
}
- cast({data, types}, attrs, [:deploy_all, :docker_tag, :clustering, :zta_provider, :zta_key])
+ cast({config, types}, attrs, [:deploy_all, :docker_tag, :clustering, :zta_provider, :zta_key])
|> validate_required([:deploy_all, :docker_tag])
end
diff --git a/lib/livebook_web/components/app_components.ex b/lib/livebook_web/components/app_components.ex
index eb7b3bfe6..4497334e3 100644
--- a/lib/livebook_web/components/app_components.ex
+++ b/lib/livebook_web/components/app_components.ex
@@ -111,6 +111,7 @@ defmodule LivebookWeb.AppComponents do
"""
attr :form, Phoenix.HTML.Form, required: true
attr :hub, :map, required: true
+ attr :disabled, :boolean, default: false
def deployment_group_form_content(assigns) do
~H"""
@@ -134,8 +135,7 @@ defmodule LivebookWeb.AppComponents do
{"Single instance", ""},
{"Fly.io", "fly_io"}
]}
- disabled={@form[:ready_only].value}
- class="disabled:cursor-not-allowed"
+ disabled={@disabled}
/>
<%= if Hubs.Provider.type(@hub) == "team" do %>
@@ -153,8 +153,7 @@ defmodule LivebookWeb.AppComponents do
}
prompt="None"
options={zta_options()}
- disabled={@form[:ready_only].value}
- class="disabled:cursor-not-allowed"
+ disabled={@disabled}
/>
<.text_field
:if={zta_metadata = zta_metadata(@form[:zta_provider].value)}
@@ -162,8 +161,7 @@ defmodule LivebookWeb.AppComponents do
label={zta_metadata.value}
placeholder={zta_placeholder(zta_metadata)}
phx-debounce
- disabled={@form[:ready_only].value}
- class="disabled:cursor-not-allowed"
+ disabled={@disabled}
/>
diff --git a/lib/livebook_web/components/form_components.ex b/lib/livebook_web/components/form_components.ex
index 3ecb37a1b..e72259bfc 100644
--- a/lib/livebook_web/components/form_components.ex
+++ b/lib/livebook_web/components/form_components.ex
@@ -421,12 +421,11 @@ defmodule LivebookWeb.FormComponents do
attr :class, :string, default: ""
attr :field, Phoenix.HTML.FormField, doc: "a form field struct retrieved from the form"
attr :help, :string, default: nil
- attr :disabled, :boolean, default: false
attr :options, :list, default: []
attr :prompt, :string, default: nil
- attr :rest, :global
+ attr :rest, :global, include: ~w(disabled)
def select_field(assigns) do
assigns = assigns_from_field(assigns)
@@ -438,7 +437,7 @@ defmodule LivebookWeb.FormComponents do
id={@id}
name={@name}
class={[
- "w-full px-3 py-2 pr-7 appearance-none bg-gray-50 text-sm border border-gray-200 rounded-lg placeholder-gray-400 text-gray-600 phx-form-error:border-red-300",
+ "w-full px-3 py-2 pr-7 appearance-none bg-gray-50 text-sm border border-gray-200 rounded-lg placeholder-gray-400 text-gray-600 phx-form-error:border-red-300 disabled:opacity-70 disabled:cursor-not-allowed",
@class
]}
{@rest}
diff --git a/lib/livebook_web/live/hub/teams/deployment_group_live.ex b/lib/livebook_web/live/hub/teams/deployment_group_live.ex
index f1450d77b..6d39e21c8 100644
--- a/lib/livebook_web/live/hub/teams/deployment_group_live.ex
+++ b/lib/livebook_web/live/hub/teams/deployment_group_live.ex
@@ -57,7 +57,9 @@ defmodule LivebookWeb.Hub.Teams.DeploymentGroupLive do
secrets: secrets,
agent_keys: agent_keys
)
- |> assign_new(:config_changeset, fn -> Hubs.Dockerfile.config_changeset() end)
+ |> assign_new(:config_changeset, fn ->
+ Hubs.Dockerfile.config_changeset(Hubs.Dockerfile.config_new())
+ end)
|> update_dockerfile()}
end
@@ -206,7 +208,7 @@ defmodule LivebookWeb.Hub.Teams.DeploymentGroupLive do
def handle_event("validate_dockerfile", %{"data" => data}, socket) do
changeset =
data
- |> Hubs.Dockerfile.config_changeset()
+ |> Hubs.Dockerfile.config_changeset(Hubs.Dockerfile.config_new())
|> Map.replace!(:action, :validate)
{:noreply,
@@ -252,12 +254,23 @@ defmodule LivebookWeb.Hub.Teams.DeploymentGroupLive do
Hubs.get_default_hub().id == hub.id
end
+ defp update_dockerfile(socket) when socket.assigns.deployment_group == nil, do: socket
+
defp update_dockerfile(socket) do
config =
socket.assigns.config_changeset
|> Ecto.Changeset.apply_changes()
|> Map.replace!(:deploy_all, true)
+ deployment_group = socket.assigns.deployment_group
+
+ config = %{
+ config
+ | clustering: deployment_group.clustering,
+ zta_provider: deployment_group.zta_provider,
+ zta_key: deployment_group.zta_key
+ }
+
%{hub: hub, secrets: deployment_group_secrets} = socket.assigns
hub_secrets = Hubs.get_secrets(hub)
diff --git a/lib/livebook_web/live/session_live/app_docker_component.ex b/lib/livebook_web/live/session_live/app_docker_component.ex
index 6773aa4fe..f08b73a08 100644
--- a/lib/livebook_web/live/session_live/app_docker_component.ex
+++ b/lib/livebook_web/live/session_live/app_docker_component.ex
@@ -10,22 +10,48 @@ defmodule LivebookWeb.SessionLive.AppDockerComponent do
@impl true
def update(assigns, socket) do
+ deployment_group_changed? =
+ not Map.has_key?(socket.assigns, :deployment_group_id) or
+ socket.assigns.deployment_group_id != assigns.deployment_group_id
+
socket = assign(socket, assigns)
deployment_groups = Provider.deployment_groups(assigns.hub)
- {:ok,
- socket
- |> assign(settings_valid?: Livebook.Notebook.AppSettings.valid?(socket.assigns.settings))
- |> assign(
- hub_secrets: Hubs.get_secrets(assigns.hub),
- hub_file_systems: Hubs.get_file_systems(assigns.hub, hub_only: true),
- deployment_groups: deployment_groups,
- deployment_group_form: %{"deployment_group_id" => assigns.deployment_group_id},
- deployment_group_id: assigns.deployment_group_id
- )
- |> assign_new(:changeset, fn -> Hubs.Dockerfile.config_changeset() end)
- |> assign_new(:save_result, fn -> nil end)
- |> update_dockerfile()}
+ socket =
+ socket
+ |> assign(settings_valid?: Livebook.Notebook.AppSettings.valid?(socket.assigns.settings))
+ |> assign(
+ hub_secrets: Hubs.get_secrets(assigns.hub),
+ hub_file_systems: Hubs.get_file_systems(assigns.hub, hub_only: true),
+ deployment_groups: deployment_groups,
+ deployment_group_form: %{"deployment_group_id" => assigns.deployment_group_id},
+ deployment_group_id: assigns.deployment_group_id
+ )
+ |> assign_new(:save_result, fn -> nil end)
+
+ socket =
+ if deployment_group_changed? do
+ assign(socket, :changeset, Hubs.Dockerfile.config_changeset(base_config(socket)))
+ else
+ socket
+ end
+
+ {:ok, update_dockerfile(socket)}
+ end
+
+ defp base_config(socket) do
+ if id = socket.assigns.deployment_group_id do
+ deployment_group = Enum.find(socket.assigns.deployment_groups, &(&1.id == id))
+
+ %{
+ Hubs.Dockerfile.config_new()
+ | clustering: deployment_group.clustering,
+ zta_provider: deployment_group.zta_provider,
+ zta_key: deployment_group.zta_key
+ }
+ else
+ Hubs.Dockerfile.config_new()
+ end
end
@impl true
@@ -128,19 +154,15 @@ defmodule LivebookWeb.SessionLive.AppDockerComponent do
<%= raw(warning) %>
- <.form
- :let={f}
- for={deployment_group_form_content(assigns)}
- as={:data}
- phx-change="validate"
- phx-target={@myself}
- >
-
-
<.form :let={f} for={@changeset} as={:data} phx-change="validate" phx-target={@myself}>
-
+
<.save_result :if={@save_result} save_result={@save_result} />
data}, socket) do
changeset =
- data
- |> Hubs.Dockerfile.config_changeset()
+ socket
+ |> base_config()
+ |> Hubs.Dockerfile.config_changeset(data)
|> Map.replace!(:action, :validate)
{:noreply, assign(socket, changeset: changeset) |> update_dockerfile()}
@@ -204,6 +227,7 @@ defmodule LivebookWeb.SessionLive.AppDockerComponent do
end
def handle_event("select_deployment_group", %{"deployment_group_id" => id}, socket) do
+ id = if(id != "", do: id)
Livebook.Session.set_notebook_deployment_group(socket.assigns.session.pid, id)
{:noreply, socket}
@@ -268,22 +292,6 @@ defmodule LivebookWeb.SessionLive.AppDockerComponent do
do: {deployment_group.name, deployment_group.id}
end
- defp deployment_group_form_content(%{deployment_group_id: id} = assigns) do
- deployment_group = if id, do: Enum.find(assigns.deployment_groups, &(&1.id == id))
-
- if deployment_group do
- %{
- "deployment_group_id" => deployment_group.id,
- "clustering" => deployment_group.clustering,
- "zta_provider" => deployment_group.zta_provider,
- "zta_key" => deployment_group.zta_key,
- "ready_only" => true
- }
- else
- assigns.changeset
- end
- end
-
defp deployment_group_help() do
"Share deployment credentials, secrets, and configuration with deployment groups."
end
diff --git a/test/livebook/hubs/dockerfile_test.exs b/test/livebook/hubs/dockerfile_test.exs
index e455671b9..0fe6450bf 100644
--- a/test/livebook/hubs/dockerfile_test.exs
+++ b/test/livebook/hubs/dockerfile_test.exs
@@ -292,8 +292,8 @@ defmodule Livebook.Hubs.DockerfileTest do
end
defp dockerfile_config(attrs \\ %{}) do
- attrs
- |> Dockerfile.config_changeset()
+ Dockerfile.config_new()
+ |> Dockerfile.config_changeset(attrs)
|> Ecto.Changeset.apply_changes()
end