defmodule LivebookWeb.Hub.SecretFormComponent do use LivebookWeb, :live_component alias Livebook.Hubs alias Livebook.Secrets alias Livebook.Secrets.Secret @impl true def mount(socket) do {:ok, assign(socket, changeset: nil, error_message: nil)} end @impl true def update(assigns, socket) do changeset = socket.assigns.changeset || Secrets.change_secret(%Secret{}, %{ name: assigns.secret_name, value: assigns.secret_value }) {:ok, socket |> assign(assigns) |> assign( title: title(socket), button: button_attrs(socket), changeset: changeset, deployment_group_id: assigns[:deployment_group_id] )} end @impl true def render(assigns) do ~H"""

<%= @title %>

<%= @error_message %>
<.form :let={f} id={"#{@id}-form"} for={@changeset} phx-target={@myself} phx-change="validate" phx-submit="save" autocomplete="off" class="basis-1/2 grow" >
<.text_field field={f[:name]} label="Name (alphanumeric and underscore)" autofocus={@secret_name == nil} spellcheck="false" autocomplete="off" readonly={@secret_name != nil} phx-debounce help="Name cannot be changed" class={secret_name_input_class(@secret_name)} /> <.password_field field={f[:value]} label="Value" autofocus={@secret_name != nil} spellcheck="false" autocomplete="off" phx-debounce /> <.hidden_field field={f[:hub_id]} value={@hub.id} /> <.hidden_field field={f[:deployment_group_id]} value={@deployment_group_id} />
<.button type="submit" disabled={not @changeset.valid?}> <.remix_icon icon={@button.icon} /> <%= @button.label %> <.button color="gray" outlined patch={@return_to}> Cancel
""" end @impl true def handle_event("save", %{"secret" => attrs}, socket) do with {:ok, secret} <- Secrets.update_secret(%Secret{}, attrs), :ok <- set_secret(socket, secret) do message = if socket.assigns.secret_name, do: "Secret #{secret.name} updated successfully", else: "Secret #{secret.name} added successfully" {:noreply, socket |> put_flash(:success, message) |> push_patch(to: socket.assigns.return_to)} else {:error, changeset} -> {:noreply, assign(socket, changeset: Map.replace!(changeset, :action, :validate))} {:transport_error, error} -> {:noreply, assign(socket, error_message: error)} end end def handle_event("validate", %{"secret" => attrs}, socket) do changeset = %Secret{} |> Secrets.change_secret(attrs) |> Map.replace!(:action, :validate) {:noreply, assign(socket, changeset: changeset)} end defp title(%{assigns: %{secret_name: nil}}), do: "Add secret" defp title(_), do: "Edit secret" defp button_attrs(%{assigns: %{secret_name: nil}}), do: %{icon: "add-line", label: "Add"} defp button_attrs(_), do: %{icon: "save-line", label: "Save"} defp set_secret(%{assigns: %{secret_name: nil}} = socket, %Secret{} = secret) do Hubs.create_secret(socket.assigns.hub, secret) end defp set_secret(socket, %Secret{} = secret) do Hubs.update_secret(socket.assigns.hub, secret) end defp secret_name_input_class(nil), do: "uppercase" defp secret_name_input_class(_), do: "uppercase bg-gray-200/50 border-200/80 cursor-not-allowed" end