defmodule LivebookWeb.Hub.Edit.TeamComponent do use LivebookWeb, :live_component alias Livebook.Hubs alias Livebook.Hubs.Provider alias Livebook.Teams alias LivebookWeb.LayoutHelpers alias LivebookWeb.TeamsComponents alias LivebookWeb.NotFoundError @impl true def update(assigns, socket) do socket = assign(socket, assigns) changeset = Teams.change_hub(assigns.hub) show_key = assigns.params["show-key"] secrets = Hubs.get_secrets(assigns.hub) file_systems = Hubs.get_file_systems(assigns.hub, hub_only: true) deployment_groups = Teams.get_deployment_groups(assigns.hub) secret_name = assigns.params["secret_name"] file_system_id = assigns.params["file_system_id"] deployment_group_id = assigns.params["deployment_group_id"] default? = default_hub?(assigns.hub) secret_value = if assigns.live_action == :edit_secret do Enum.find_value(secrets, &(&1.name == secret_name and &1.value)) || raise(NotFoundError, "could not find secret matching #{inspect(secret_name)}") end file_system = if assigns.live_action == :edit_file_system do Enum.find_value(file_systems, &(&1.id == file_system_id && &1)) || raise(NotFoundError, "could not find file system matching #{inspect(file_system_id)}") end deployment_group = if assigns.live_action == :edit_deployment_group do Enum.find_value(deployment_groups, &(&1.id == deployment_group_id && &1)) || raise( NotFoundError, "could not find deployment group matching #{inspect(deployment_group_id)}" ) end {:ok, socket |> assign( secrets: secrets, file_system: file_system, file_system_id: file_system_id, file_systems: file_systems, deployment_group_id: deployment_group_id, deployment_group: deployment_group, deployment_groups: deployment_groups, show_key: show_key, secret_name: secret_name, secret_value: secret_value, hub_metadata: Provider.to_metadata(assigns.hub), default?: default? ) |> assign_form(changeset)} end @impl true def render(assigns) do ~H"""
<%= Provider.connection_error(@hub) %>

<.remix_icon icon="mail-line" /> Invite users <.remix_icon icon="settings-line" /> Manage organization <.link patch={~p"/hub/#{@hub.id}?show-key=yes"} class="hover:text-blue-600 cursor-pointer" > <.remix_icon icon="key-2-fill" /> Display Teams key <%= if @default? do %> <% else %> <% end %>

General

<.form :let={f} id={@id} class="flex flex-col mt-4 space-y-4" for={@form} phx-submit="save" phx-change="validate" phx-target={@myself} >
<.text_field field={f[:hub_name]} label="Name" disabled help="Name cannot be changed" class="bg-gray-200/50 border-200/80 cursor-not-allowed" /> <.emoji_field field={f[:hub_emoji]} label="Emoji" />

Secrets

Secrets are a safe way to share credentials and tokens with notebooks. They are often used by Smart cells and can be read as environment variables using the LB_ prefix.

<.live_component module={LivebookWeb.Hub.SecretListComponent} id="hub-secrets-list" hub={@hub} secrets={@secrets} add_path={~p"/hub/#{@hub.id}/secrets/new"} edit_path={"hub/#{@hub.id}/secrets/edit"} return_to={~p"/hub/#{@hub.id}"} target={@myself} />

File storages

File storages are used to store notebooks and their files.

<.live_component module={LivebookWeb.Hub.FileSystemListComponent} id="hub-file-systems-list" hub_id={@hub.id} file_systems={@file_systems} target={@myself} />

Deployment groups

Deployment groups.

<.live_component module={LivebookWeb.Hub.Teams.DeploymentGroupListComponent} id="hub-deployment-groups-list" hub_id={@hub.id} deployment_groups={@deployment_groups} target={@myself} />

Danger zone

Delete this hub

This only removes the hub from this machine. You must rejoin to access its features once again.

<.modal :if={@show_key} id="key-modal" show width={:medium} patch={~p"/hub/#{@hub.id}"}> <.teams_key_modal teams_key={@hub.teams_key} confirm_url={if @show_key == "confirm", do: ~p"/hub/#{@hub.id}"} /> <.modal :if={@live_action in [:new_secret, :edit_secret]} id="secrets-modal" show width={:medium} patch={~p"/hub/#{@hub.id}"} > <.live_component module={LivebookWeb.Hub.SecretFormComponent} id="secrets" hub={@hub} secret_name={@secret_name} secret_value={@secret_value} return_to={~p"/hub/#{@hub.id}"} /> <.modal :if={@live_action in [:new_file_system, :edit_file_system]} id="file-systems-modal" show width={:medium} patch={~p"/hub/#{@hub.id}"} > <.live_component module={LivebookWeb.Hub.FileSystemFormComponent} id="file-systems" hub={@hub} file_system={@file_system} file_system_id={@file_system_id} return_to={~p"/hub/#{@hub.id}"} />
""" end defp org_url(hub, path) do Livebook.Config.teams_url() <> "/orgs/#{hub.org_id}" <> path end defp teams_key_modal(assigns) do ~H"""

Teams key

This is your Teams key. This key encrypts your data before it is sent to Livebook Teams servers. This key is required for you and invited users to join this organization. We recommend storing it somewhere safe:
<.link :if={@confirm_url} patch={@confirm_url} class="button-base button-blue block text-center"> <.remix_icon class="mr-2" icon="thumb-up-fill" /> I've saved my Teams key in a secure location
""" end @impl true def handle_event("save", %{"team" => params}, socket) do case Teams.update_hub(socket.assigns.hub, params) do {:ok, hub} -> {:noreply, socket |> put_flash(:success, "Hub updated successfully") |> push_patch(to: ~p"/hub/#{hub.id}")} {:error, changeset} -> {:noreply, assign_form(socket, changeset)} end end def handle_event("validate", %{"team" => attrs}, socket) do changeset = socket.assigns.hub |> Teams.change_hub(attrs) |> Map.replace!(:action, :validate) {:noreply, assign_form(socket, changeset)} end def handle_event("delete_hub_secret", attrs, socket) do %{hub: hub} = socket.assigns on_confirm = fn socket -> {:ok, secret} = Livebook.Secrets.update_secret(%Livebook.Secrets.Secret{}, attrs) case Livebook.Hubs.delete_secret(hub, secret) do :ok -> socket {:transport_error, reason} -> put_flash(socket, :error, reason) end end {:noreply, confirm(socket, on_confirm, title: "Delete hub secret - #{attrs["name"]}", description: "Are you sure you want to delete this hub secret?", confirm_text: "Delete", confirm_icon: "delete-bin-6-line" )} end def handle_event("mark_as_default", _, socket) do Hubs.set_default_hub(socket.assigns.hub.id) {:noreply, assign(socket, default?: true)} end def handle_event("remove_as_default", _, socket) do Hubs.unset_default_hub() {:noreply, assign(socket, default?: false)} end defp default_hub?(hub) do Hubs.get_default_hub().id == hub.id end defp assign_form(socket, %Ecto.Changeset{} = changeset) do assign(socket, form: to_form(changeset)) end end