diff --git a/assets/js/hooks/emoji_picker.js b/assets/js/hooks/emoji_picker.js new file mode 100644 index 000000000..762b77865 --- /dev/null +++ b/assets/js/hooks/emoji_picker.js @@ -0,0 +1,33 @@ +import { createPicker } from "picmo"; + +/** + * A hook for the emoji picker input. + */ +const EmojiPicker = { + mounted() { + const rootElement = this.el.querySelector("[data-emoji-container]"); + const preview = this.el.querySelector("[data-emoji-preview]"); + const input = this.el.querySelector("[data-emoji-input]"); + const button = this.el.querySelector("[data-emoji-button]"); + + const pickerOptions = { + rootElement, + showSearch: false, + showPreview: false, + }; + + const picker = createPicker(pickerOptions); + + picker.addEventListener("emoji:select", ({ emoji }) => { + preview.innerHTML = emoji; + input.value = emoji; + rootElement.classList.toggle("hidden"); + }); + + button.addEventListener("click", (_) => { + rootElement.classList.toggle("hidden"); + }); + }, +}; + +export default EmojiPicker; diff --git a/assets/js/hooks/index.js b/assets/js/hooks/index.js index 4200acd85..b53922226 100644 --- a/assets/js/hooks/index.js +++ b/assets/js/hooks/index.js @@ -4,6 +4,7 @@ import CellEditor from "./cell_editor"; import ConfirmModal from "./confirm_modal"; import Dropzone from "./dropzone"; import EditorSettings from "./editor_settings"; +import EmojiPicker from "./emoji_picker"; import FocusOnUpdate from "./focus_on_update"; import Headline from "./headline"; import Highlight from "./highlight"; @@ -26,6 +27,7 @@ export default { ConfirmModal, Dropzone, EditorSettings, + EmojiPicker, FocusOnUpdate, Headline, Highlight, diff --git a/assets/package-lock.json b/assets/package-lock.json index 9e9666b35..eac9a9a91 100644 --- a/assets/package-lock.json +++ b/assets/package-lock.json @@ -21,6 +21,7 @@ "phoenix": "file:../deps/phoenix", "phoenix_html": "file:../deps/phoenix_html", "phoenix_live_view": "file:../deps/phoenix_live_view", + "picmo": "^5.7.2", "postcss-import": "^15.0.0", "postcss-loader": "^7.0.1", "rehype-katex": "^6.0.0", @@ -4505,6 +4506,15 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, + "node_modules/emojibase": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/emojibase/-/emojibase-6.1.0.tgz", + "integrity": "sha512-1GkKJPXP6tVkYJHOBSJHoGOr/6uaDxZ9xJ6H7m6PfdGXTmQgbALHLWaVRY4Gi/qf5x/gT/NUXLPuSHYLqtLtrQ==", + "funding": { + "type": "ko-fi", + "url": "https://ko-fi.com/milesjohnson" + } + }, "node_modules/emojis-list": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", @@ -8544,6 +8554,17 @@ "resolved": "../deps/phoenix_live_view", "link": true }, + "node_modules/picmo": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/picmo/-/picmo-5.7.2.tgz", + "integrity": "sha512-A7c5O8x1Xwq11KBYFY93+GIbHnw9PVz35HaWWHn/dgT08GA67M6cXKjjwzLnEAyXSdxXKrEk8/gPyTs+ibzWfQ==", + "dependencies": { + "emojibase": "^6.1.0" + }, + "funding": { + "url": "https://github.com/sponsors/joeattardi" + } + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -14080,6 +14101,11 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, + "emojibase": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/emojibase/-/emojibase-6.1.0.tgz", + "integrity": "sha512-1GkKJPXP6tVkYJHOBSJHoGOr/6uaDxZ9xJ6H7m6PfdGXTmQgbALHLWaVRY4Gi/qf5x/gT/NUXLPuSHYLqtLtrQ==" + }, "emojis-list": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", @@ -16897,6 +16923,14 @@ "phoenix_live_view": { "version": "file:../deps/phoenix_live_view" }, + "picmo": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/picmo/-/picmo-5.7.2.tgz", + "integrity": "sha512-A7c5O8x1Xwq11KBYFY93+GIbHnw9PVz35HaWWHn/dgT08GA67M6cXKjjwzLnEAyXSdxXKrEk8/gPyTs+ibzWfQ==", + "requires": { + "emojibase": "^6.1.0" + } + }, "picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", diff --git a/assets/package.json b/assets/package.json index 451eb2826..493fd4edd 100644 --- a/assets/package.json +++ b/assets/package.json @@ -25,6 +25,7 @@ "phoenix": "file:../deps/phoenix", "phoenix_html": "file:../deps/phoenix_html", "phoenix_live_view": "file:../deps/phoenix_live_view", + "picmo": "^5.7.2", "postcss-import": "^15.0.0", "postcss-loader": "^7.0.1", "rehype-katex": "^6.0.0", diff --git a/lib/livebook/application.ex b/lib/livebook/application.ex index 806f3a373..08fb13049 100644 --- a/lib/livebook/application.ex +++ b/lib/livebook/application.ex @@ -197,13 +197,11 @@ defmodule Livebook.Application do if Livebook.Config.feature_flag_enabled?(:localhost_hub) do defp insert_development_hub do - unless Livebook.Hubs.hub_exists?("local-host") do - Livebook.Hubs.save_hub(%Livebook.Hubs.Local{ - id: "local-host", - hub_name: "Localhost", - hub_color: Livebook.EctoTypes.HexColor.random() - }) - end + Livebook.Hubs.save_hub(%Livebook.Hubs.Local{ + id: "local-host", + hub_name: "Localhost", + hub_emoji: "🏠" + }) end else defp insert_development_hub, do: :ok diff --git a/lib/livebook/hubs.ex b/lib/livebook/hubs.ex index d3e94e8b3..ddfa4ee1f 100644 --- a/lib/livebook/hubs.ex +++ b/lib/livebook/hubs.ex @@ -2,7 +2,7 @@ defmodule Livebook.Hubs do @moduledoc false alias Livebook.Storage - alias Livebook.Hubs.{Enterprise, Fly, Local, Metadata, Provider} + alias Livebook.Hubs.{Broadcasts, Enterprise, Fly, Local, Metadata, Provider} @namespace :hubs @@ -28,7 +28,7 @@ defmodule Livebook.Hubs do @spec get_metadatas() :: list(Metadata.t()) def get_metadatas do for hub <- get_hubs() do - Provider.normalize(hub) + %{Provider.normalize(hub) | connected?: Provider.connected?(hub)} end end @@ -71,7 +71,7 @@ defmodule Livebook.Hubs do attributes = struct |> Map.from_struct() |> Map.to_list() :ok = Storage.insert(@namespace, struct.id, attributes) :ok = connect_hub(struct) - :ok = broadcast_hubs_change() + :ok = Broadcasts.hubs_metadata_changed() struct end @@ -84,7 +84,7 @@ defmodule Livebook.Hubs do end :ok = Storage.delete(@namespace, id) - :ok = broadcast_hubs_change() + :ok = Broadcasts.hubs_metadata_changed() end :ok @@ -98,30 +98,50 @@ defmodule Livebook.Hubs do end @doc """ - Subscribes to updates in hubs information. + Subscribes to one or more subtopics in `"hubs"`. ## Messages - * `{:hubs_metadata_changed, hubs}` + Topic `hubs:crud`: + + * `:hubs_metadata_changed` + + Topic `hubs:connection`: + + * `:hub_connected` + * `:hub_disconnected` + * `{:connection_error, reason}` + * `{:disconnection_error, reason}` + + Topic `hubs:secrets`: + + * `{:secret_created, %Secret{}}` + * `{:secret_updated, %Secret{}}` """ - @spec subscribe() :: :ok | {:error, term()} - def subscribe do - Phoenix.PubSub.subscribe(Livebook.PubSub, "hubs") + @spec subscribe(atom() | list(atom())) :: :ok | {:error, term()} + def subscribe(topics) when is_list(topics) do + for topic <- topics, do: subscribe(topic) + + :ok + end + + def subscribe(topic) do + Phoenix.PubSub.subscribe(Livebook.PubSub, "hubs:#{topic}") end @doc """ Unsubscribes from `subscribe/0`. """ - @spec unsubscribe() :: :ok - def unsubscribe do - Phoenix.PubSub.unsubscribe(Livebook.PubSub, "hubs") + @spec unsubscribe(atom() | list(atom())) :: :ok + def unsubscribe(topics) when is_list(topics) do + for topic <- topics, do: unsubscribe(topic) + + :ok end - # Notifies interested processes about hubs data change. - # Broadcasts `{:hubs_metadata_changed, hubs}` message under the `"hubs"` topic. - defp broadcast_hubs_change do - Phoenix.PubSub.broadcast(Livebook.PubSub, "hubs", {:hubs_metadata_changed, get_metadatas()}) + def unsubscribe(topic) do + Phoenix.PubSub.unsubscribe(Livebook.PubSub, "hubs:#{topic}") end defp to_struct(%{id: "fly-" <> _} = fields) do diff --git a/lib/livebook/hubs/broadcasts.ex b/lib/livebook/hubs/broadcasts.ex new file mode 100644 index 000000000..74ee89cad --- /dev/null +++ b/lib/livebook/hubs/broadcasts.ex @@ -0,0 +1,71 @@ +defmodule Livebook.Hubs.Broadcasts do + @moduledoc false + + alias Livebook.Secrets.Secret + + @type broadcast :: :ok | {:error, term()} + + @crud_topic "hubs:crud" + @connection_topic "hubs:connection" + @secrets_topic "hubs:secrets" + + @doc """ + Broadcasts when hubs changed under `hubs:crud` topic + """ + @spec hubs_metadata_changed() :: broadcast() + def hubs_metadata_changed do + broadcast(@crud_topic, :hubs_metadata_changed) + end + + @doc """ + Broadcasts when hub connected under `hubs:connection` topic + """ + @spec hub_connected() :: broadcast() + def hub_connected do + broadcast(@connection_topic, :hub_connected) + end + + @doc """ + Broadcasts when hub disconnected under `hubs:connection` topic + """ + @spec hub_disconnected() :: broadcast() + def hub_disconnected do + broadcast(@connection_topic, :hub_disconnected) + end + + @doc """ + Broadcasts when hub had an error when connecting under `hubs:connection` topic + """ + @spec hub_connection_failed(String.t()) :: broadcast() + def hub_connection_failed(reason) when is_binary(reason) do + broadcast(@connection_topic, {:connection_error, reason}) + end + + @doc """ + Broadcasts when hub had an error when disconnecting under `hubs:connection` topic + """ + @spec hub_disconnection_failed(String.t()) :: broadcast() + def hub_disconnection_failed(reason) when is_binary(reason) do + broadcast(@connection_topic, {:disconnection_error, reason}) + end + + @doc """ + Broadcasts when hub received a new secret under `hubs:secrets` topic + """ + @spec secret_created(Secret.t()) :: broadcast() + def secret_created(%Secret{} = secret) do + broadcast(@secrets_topic, {:secret_created, secret}) + end + + @doc """ + Broadcasts when hub received an updated secret under `hubs:secrets` topic + """ + @spec secret_updated(Secret.t()) :: broadcast() + def secret_updated(%Secret{} = secret) do + broadcast(@secrets_topic, {:secret_updated, secret}) + end + + defp broadcast(topic, message) do + Phoenix.PubSub.broadcast(Livebook.PubSub, topic, message) + end +end diff --git a/lib/livebook/hubs/enterprise.ex b/lib/livebook/hubs/enterprise.ex index 49358d276..c85e02e45 100644 --- a/lib/livebook/hubs/enterprise.ex +++ b/lib/livebook/hubs/enterprise.ex @@ -12,7 +12,7 @@ defmodule Livebook.Hubs.Enterprise do token: String.t() | nil, external_id: String.t() | nil, hub_name: String.t() | nil, - hub_color: String.t() | nil + hub_emoji: String.t() | nil } embedded_schema do @@ -20,7 +20,7 @@ defmodule Livebook.Hubs.Enterprise do field :token, :string field :external_id, :string field :hub_name, :string - field :hub_color, Livebook.EctoTypes.HexColor + field :hub_emoji, :string end @fields ~w( @@ -28,7 +28,7 @@ defmodule Livebook.Hubs.Enterprise do token external_id hub_name - hub_color + hub_emoji )a @doc """ @@ -113,7 +113,7 @@ defimpl Livebook.Hubs.Provider, for: Livebook.Hubs.Enterprise do token: fields.token, external_id: fields.external_id, hub_name: fields.hub_name, - hub_color: fields.hub_color + hub_emoji: fields.hub_emoji } end @@ -122,7 +122,7 @@ defimpl Livebook.Hubs.Provider, for: Livebook.Hubs.Enterprise do id: enterprise.id, name: enterprise.hub_name, provider: enterprise, - color: enterprise.hub_color + emoji: enterprise.hub_emoji } end @@ -130,4 +130,8 @@ defimpl Livebook.Hubs.Provider, for: Livebook.Hubs.Enterprise do def connect(%Livebook.Hubs.Enterprise{} = enterprise), do: {Livebook.Hubs.EnterpriseClient, enterprise} + + def connected?(%Livebook.Hubs.Enterprise{id: id}) do + Livebook.Hubs.EnterpriseClient.connected?(id) + end end diff --git a/lib/livebook/hubs/enterprise_client.ex b/lib/livebook/hubs/enterprise_client.ex index 04db576c3..d2361f2ad 100644 --- a/lib/livebook/hubs/enterprise_client.ex +++ b/lib/livebook/hubs/enterprise_client.ex @@ -2,21 +2,31 @@ defmodule Livebook.Hubs.EnterpriseClient do @moduledoc false use GenServer + alias Livebook.Hubs.Broadcasts alias Livebook.Hubs.Enterprise alias Livebook.Secrets.Secret alias Livebook.WebSocket.Server - @pubsub_topic "enterprise" @registry Livebook.HubsRegistry - defstruct [:server, :hub, secrets: []] + defstruct [:server, :hub, connected?: false, secrets: []] @doc """ Connects the Enterprise client with WebSocket server. """ @spec start_link(Enterprise.t()) :: GenServer.on_start() def start_link(%Enterprise{} = enterprise) do - GenServer.start_link(__MODULE__, enterprise, name: registry_name(enterprise)) + GenServer.start_link(__MODULE__, enterprise, name: registry_name(enterprise.id)) + end + + @doc """ + Stops the WebSocket server. + """ + @spec stop(pid()) :: :ok + def stop(pid) do + pid |> GenServer.call(:get_server) |> GenServer.stop() + + :ok end @doc """ @@ -36,27 +46,15 @@ defmodule Livebook.Hubs.EnterpriseClient do end @doc """ - Subscribe to WebSocket Server events. - - ## Messages - - * `{:connect, :ok, :connected}` - * `{:connect, :error, reason}` - * `{:secret_created, %Secret{}}` - * `{:secret_updated, %Secret{}}` - + Returns if the given enterprise is connected. """ - @spec subscribe() :: :ok | {:error, {:already_registered, pid()}} - def subscribe do - Phoenix.PubSub.subscribe(Livebook.PubSub, @pubsub_topic) - end - - @doc """ - Unsubscribes from `subscribe/0`. - """ - @spec unsubscribe() :: :ok - def unsubscribe do - Phoenix.PubSub.unsubscribe(Livebook.PubSub, @pubsub_topic) + @spec connected?(String.t()) :: boolean() + def connected?(id) do + try do + GenServer.call(registry_name(id), :connected?) + catch + :exit, _ -> false + end end ## GenServer callbacks @@ -78,44 +76,48 @@ defmodule Livebook.Hubs.EnterpriseClient do {:reply, state.secrets, state} end - @impl true - def handle_info({:connect, _, _} = message, state) do - broadcast_message(message) - {:noreply, state} + def handle_call(:connected?, _caller, state) do + {:reply, state.connected?, state} end - def handle_info({:disconnect, :error, _} = message, state) do - broadcast_message(message) - {:noreply, state} + @impl true + def handle_info({:connect, :ok, _}, state) do + Broadcasts.hub_connected() + {:noreply, %{state | connected?: true}} + end + + def handle_info({:connect, :error, reason}, state) do + Broadcasts.hub_connection_failed(reason) + {:noreply, %{state | connected?: false}} + end + + def handle_info({:disconnect, :error, reason}, state) do + Broadcasts.hub_disconnection_failed(reason) + {:noreply, %{state | connected?: false}} end def handle_info({:event, :secret_created, %{name: name, value: value}}, state) do secret = %Secret{name: name, value: value} - broadcast_message({:secret_created, secret}) + Broadcasts.secret_created(secret) {:noreply, put_secret(state, secret)} end def handle_info({:event, :secret_updated, %{name: name, value: value}}, state) do secret = %Secret{name: name, value: value} - broadcast_message({:secret_updated, secret}) + Broadcasts.secret_updated(secret) {:noreply, put_secret(state, secret)} end def handle_info({:disconnect, :ok, :disconnected}, state) do + Broadcasts.hub_disconnected() {:stop, :normal, state} end # Private - # Notifies interested processes about WebSocket Server messages. - # Broadcasts the given message under the `"enterprise"` topic. - defp broadcast_message(message) do - Phoenix.PubSub.broadcast(Livebook.PubSub, @pubsub_topic, message) - end - - defp registry_name(%Enterprise{id: id}) do + defp registry_name(id) do {:via, Registry, {@registry, id}} end diff --git a/lib/livebook/hubs/fly.ex b/lib/livebook/hubs/fly.ex index 62669d236..cb56e4cbd 100644 --- a/lib/livebook/hubs/fly.ex +++ b/lib/livebook/hubs/fly.ex @@ -10,7 +10,7 @@ defmodule Livebook.Hubs.Fly do id: String.t() | nil, access_token: String.t() | nil, hub_name: String.t() | nil, - hub_color: String.t() | nil, + hub_emoji: String.t() | nil, organization_id: String.t() | nil, organization_type: String.t() | nil, organization_name: String.t() | nil, @@ -20,7 +20,7 @@ defmodule Livebook.Hubs.Fly do embedded_schema do field :access_token, :string field :hub_name, :string - field :hub_color, Livebook.EctoTypes.HexColor + field :hub_emoji, :string field :organization_id, :string field :organization_type, :string field :organization_name, :string @@ -30,7 +30,7 @@ defmodule Livebook.Hubs.Fly do @fields ~w( access_token hub_name - hub_color + hub_emoji organization_id organization_name organization_type @@ -116,7 +116,7 @@ defimpl Livebook.Hubs.Provider, for: Livebook.Hubs.Fly do | id: fields.id, access_token: fields.access_token, hub_name: fields.hub_name, - hub_color: fields.hub_color, + hub_emoji: fields.hub_emoji, organization_id: fields.organization_id, organization_type: fields.organization_type, organization_name: fields.organization_name, @@ -129,11 +129,13 @@ defimpl Livebook.Hubs.Provider, for: Livebook.Hubs.Fly do id: fly.id, name: fly.hub_name, provider: fly, - color: fly.hub_color + emoji: fly.hub_emoji } end def type(_fly), do: "fly" def connect(_fly), do: nil + + def connected?(_fly), do: false end diff --git a/lib/livebook/hubs/local.ex b/lib/livebook/hubs/local.ex index 009f61142..5f96a93cd 100644 --- a/lib/livebook/hubs/local.ex +++ b/lib/livebook/hubs/local.ex @@ -1,12 +1,12 @@ defmodule Livebook.Hubs.Local do @moduledoc false - defstruct [:id, :hub_name, :hub_color] + defstruct [:id, :hub_name, :hub_emoji] end defimpl Livebook.Hubs.Provider, for: Livebook.Hubs.Local do def load(%Livebook.Hubs.Local{} = local, fields) do - %{local | id: fields.id, hub_name: fields.hub_name, hub_color: fields.hub_color} + %{local | id: fields.id, hub_name: fields.hub_name, hub_emoji: fields.hub_emoji} end def normalize(%Livebook.Hubs.Local{} = local) do @@ -14,11 +14,13 @@ defimpl Livebook.Hubs.Provider, for: Livebook.Hubs.Local do id: local.id, name: local.hub_name, provider: local, - color: local.hub_color + emoji: local.hub_emoji } end def type(_local), do: "local" def connect(_local), do: nil + + def connected?(_local), do: false end diff --git a/lib/livebook/hubs/metadata.ex b/lib/livebook/hubs/metadata.ex index 59272b0ea..60acbb2cb 100644 --- a/lib/livebook/hubs/metadata.ex +++ b/lib/livebook/hubs/metadata.ex @@ -1,12 +1,13 @@ defmodule Livebook.Hubs.Metadata do @moduledoc false - defstruct [:id, :name, :provider, :color] + defstruct [:id, :name, :provider, :emoji, connected?: false] @type t :: %__MODULE__{ id: String.t(), name: String.t(), provider: struct(), - color: String.t() + emoji: String.t(), + connected?: boolean() } end diff --git a/lib/livebook/hubs/provider.ex b/lib/livebook/hubs/provider.ex index 3c54b92f7..833fa1a76 100644 --- a/lib/livebook/hubs/provider.ex +++ b/lib/livebook/hubs/provider.ex @@ -24,4 +24,10 @@ defprotocol Livebook.Hubs.Provider do """ @spec connect(struct()) :: Supervisor.child_spec() | module() | {module(), any()} | nil def connect(struct) + + @doc """ + Gets the connection status of the given struct. + """ + @spec connected?(struct()) :: boolean() + def connected?(struct) end diff --git a/lib/livebook_web/live/form_helpers.ex b/lib/livebook_web/live/form_helpers.ex index 901367520..a43d60b74 100644 --- a/lib/livebook_web/live/form_helpers.ex +++ b/lib/livebook_web/live/form_helpers.ex @@ -2,7 +2,6 @@ defmodule LivebookWeb.FormHelpers do @moduledoc """ Conveniences for translating and building error messages. """ - use Phoenix.Component import Phoenix.HTML.Form @@ -55,6 +54,38 @@ defmodule LivebookWeb.FormHelpers do """ end + @doc """ + Emoji input. + """ + def emoji_input(assigns) do + ~H""" +
+
+
+
+ <%= input_value(@form, @field) %> +
+
+ +
+ +
+ +
+ +
+ """ + end + @doc """ Translates an error message. """ diff --git a/lib/livebook_web/live/hooks/sidebar_hook.ex b/lib/livebook_web/live/hooks/sidebar_hook.ex index d8c92212b..3c7837955 100644 --- a/lib/livebook_web/live/hooks/sidebar_hook.ex +++ b/lib/livebook_web/live/hooks/sidebar_hook.ex @@ -6,7 +6,7 @@ defmodule LivebookWeb.SidebarHook do def on_mount(:default, _params, _session, socket) do if connected?(socket) do - Livebook.Hubs.subscribe() + Livebook.Hubs.subscribe([:crud, :connection]) end socket = @@ -18,8 +18,16 @@ defmodule LivebookWeb.SidebarHook do {:cont, socket} end - defp handle_info({:hubs_metadata_changed, hubs}, socket) do - {:halt, assign(socket, saved_hubs: hubs)} + @connection_events ~w(hub_connected hub_disconnected hubs_metadata_changed)a + + defp handle_info(event, socket) when event in @connection_events do + {:halt, assign(socket, saved_hubs: Livebook.Hubs.get_metadatas())} + end + + @error_events ~w(connection_error disconnection_error)a + + defp handle_info({event, _reason}, socket) when event in @error_events do + {:halt, assign(socket, saved_hubs: Livebook.Hubs.get_metadatas())} end defp handle_info(_event, socket), do: {:cont, socket} diff --git a/lib/livebook_web/live/hooks/user_hook.ex b/lib/livebook_web/live/hooks/user_hook.ex index 03cb0e928..541bbe91a 100644 --- a/lib/livebook_web/live/hooks/user_hook.ex +++ b/lib/livebook_web/live/hooks/user_hook.ex @@ -21,7 +21,7 @@ defmodule LivebookWeb.UserHook do {:user_change, %{id: id} = user}, %{assigns: %{current_user: %{id: id}}} = socket ) do - {:cont, assign(socket, :current_user, user)} + {:halt, assign(socket, :current_user, user)} end defp info(_message, socket), do: {:cont, socket} diff --git a/lib/livebook_web/live/hub/edit/enterprise_component.ex b/lib/livebook_web/live/hub/edit/enterprise_component.ex index 9d17c03c3..06030fff8 100644 --- a/lib/livebook_web/live/hub/edit/enterprise_component.ex +++ b/lib/livebook_web/live/hub/edit/enterprise_component.ex @@ -1,7 +1,6 @@ defmodule LivebookWeb.Hub.Edit.EnterpriseComponent do use LivebookWeb, :live_component - alias Livebook.EctoTypes.HexColor alias Livebook.Hubs.Enterprise @impl true @@ -35,13 +34,9 @@ defmodule LivebookWeb.Hub.Edit.EnterpriseComponent do phx-debounce="blur" >
- <.input_wrapper form={f} field={:hub_color} class="flex flex-col space-y-1"> -
Color
- <.hex_color_input - form={f} - field={:hub_color} - randomize={JS.push("randomize_color", target: @myself)} - /> + <.input_wrapper form={f} field={:hub_emoji} class="flex flex-col space-y-1"> +
Emoji
+ <.emoji_input id="enterprise-emoji-input" form={f} field={:hub_emoji} />
@@ -58,10 +53,6 @@ defmodule LivebookWeb.Hub.Edit.EnterpriseComponent do end @impl true - def handle_event("randomize_color", _, socket) do - handle_event("validate", %{"enterprise" => %{"hub_color" => HexColor.random()}}, socket) - end - def handle_event("save", %{"enterprise" => params}, socket) do case Enterprise.update_hub(socket.assigns.hub, params) do {:ok, hub} -> diff --git a/lib/livebook_web/live/hub/edit/fly_component.ex b/lib/livebook_web/live/hub/edit/fly_component.ex index 8cec534ea..5e227bd74 100644 --- a/lib/livebook_web/live/hub/edit/fly_component.ex +++ b/lib/livebook_web/live/hub/edit/fly_component.ex @@ -1,7 +1,6 @@ defmodule LivebookWeb.Hub.Edit.FlyComponent do use LivebookWeb, :live_component - alias Livebook.EctoTypes.HexColor alias Livebook.Hubs.{Fly, FlyClient} @impl true @@ -76,13 +75,9 @@ defmodule LivebookWeb.Hub.Edit.FlyComponent do <%= text_input(f, :hub_name, class: "input") %> - <.input_wrapper form={f} field={:hub_color} class="flex flex-col space-y-1"> -
Color
- <.hex_color_input - form={f} - field={:hub_color} - randomize={JS.push("randomize_color", target: @myself)} - /> + <.input_wrapper form={f} field={:hub_emoji} class="flex flex-col space-y-1"> +
Emoji
+ <.emoji_input id="fly-emoji-input" form={f} field={:hub_emoji} />
@@ -134,10 +129,6 @@ defmodule LivebookWeb.Hub.Edit.FlyComponent do end @impl true - def handle_event("randomize_color", _, socket) do - handle_event("validate", %{"fly" => %{"hub_color" => HexColor.random()}}, socket) - end - def handle_event("save", %{"fly" => params}, socket) do case Fly.update_hub(socket.assigns.hub, params) do {:ok, hub} -> diff --git a/lib/livebook_web/live/hub/new/enterprise_component.ex b/lib/livebook_web/live/hub/new/enterprise_component.ex index ac9860482..d04bbc211 100644 --- a/lib/livebook_web/live/hub/new/enterprise_component.ex +++ b/lib/livebook_web/live/hub/new/enterprise_component.ex @@ -3,13 +3,12 @@ defmodule LivebookWeb.Hub.New.EnterpriseComponent do import Ecto.Changeset, only: [get_field: 2] - alias Livebook.EctoTypes.HexColor alias Livebook.Hubs.{Enterprise, EnterpriseClient} @impl true def update(assigns, socket) do if connected?(socket) do - EnterpriseClient.subscribe() + Livebook.Hubs.subscribe(:connection) end {:ok, @@ -82,13 +81,9 @@ defmodule LivebookWeb.Hub.New.EnterpriseComponent do <%= text_input(f, :hub_name, class: "input", readonly: true) %> - <.input_wrapper form={f} field={:hub_color} class="flex flex-col space-y-1"> -
Color
- <.hex_color_input - form={f} - field={:hub_color} - randomize={JS.push("randomize_color", target: @myself)} - /> + <.input_wrapper form={f} field={:hub_emoji} class="flex flex-col space-y-1"> +
Emoji
+ <.emoji_input id="enterprise-emoji-input" form={f} field={:hub_emoji} />
@@ -109,20 +104,26 @@ defmodule LivebookWeb.Hub.New.EnterpriseComponent do token = get_field(socket.assigns.changeset, :token) base = %Enterprise{ + id: "enterprise-placeholder", token: token, + external_id: "placeholder", url: url, hub_name: "Enterprise", - hub_color: HexColor.random() + hub_emoji: "🏭" } {:ok, pid} = EnterpriseClient.start_link(base) receive do - {:connect, :error, reason} -> - GenServer.stop(pid) - handle_error(reason, socket) + {:connection_error, reason} -> + EnterpriseClient.stop(pid) - {:connect, :ok, :connected} -> + {:noreply, + socket + |> put_flash(:error, "Failed to connect with Enterprise: " <> reason) + |> push_patch(to: Routes.hub_path(socket, :new))} + + :hub_connected -> session_request = LivebookProto.SessionRequest.new!(app_version: Livebook.Config.app_version()) @@ -134,16 +135,16 @@ defmodule LivebookWeb.Hub.New.EnterpriseComponent do {:noreply, assign(socket, pid: pid, changeset: changeset, base: base)} {:error, reason} -> - GenServer.stop(pid) - handle_error(reason, socket) + EnterpriseClient.stop(pid) + + {:noreply, + socket + |> put_flash(:error, "Failed to connect with Enterprise: " <> reason) + |> push_patch(to: Routes.hub_path(socket, :new))} end end end - def handle_event("randomize_color", _, socket) do - handle_event("validate", %{"enterprise" => %{"hub_color" => HexColor.random()}}, socket) - end - def handle_event("save", %{"enterprise" => params}, socket) do if socket.assigns.changeset.valid? do case Enterprise.create_hub(socket.assigns.base, params) do @@ -168,23 +169,4 @@ defmodule LivebookWeb.Hub.New.EnterpriseComponent do def handle_event("validate", %{"enterprise" => attrs}, socket) do {:noreply, assign(socket, changeset: Enterprise.change_hub(socket.assigns.base, attrs))} end - - def handle_error(%{reason: :econnrefused}, socket) do - show_connect_error("Failed to connect with given URL", socket) - end - - def handle_error(%{reason: _}, socket) do - show_connect_error("Failed to connect with Enterprise", socket) - end - - def handle_error(reason, socket) do - show_connect_error(reason, socket) - end - - defp show_connect_error(message, socket) do - {:noreply, - socket - |> put_flash(:error, message) - |> push_patch(to: Routes.hub_path(socket, :new))} - end end diff --git a/lib/livebook_web/live/hub/new/fly_component.ex b/lib/livebook_web/live/hub/new/fly_component.ex index b8f990ebf..2597ed15b 100644 --- a/lib/livebook_web/live/hub/new/fly_component.ex +++ b/lib/livebook_web/live/hub/new/fly_component.ex @@ -3,7 +3,6 @@ defmodule LivebookWeb.Hub.New.FlyComponent do import Ecto.Changeset, only: [get_field: 2, add_error: 3] - alias Livebook.EctoTypes.HexColor alias Livebook.Hubs.{Fly, FlyClient} @impl true @@ -60,13 +59,9 @@ defmodule LivebookWeb.Hub.New.FlyComponent do <%= text_input(f, :hub_name, class: "input") %> - <.input_wrapper form={f} field={:hub_color} class="flex flex-col space-y-1"> -
Color
- <.hex_color_input - form={f} - field={:hub_color} - randomize={JS.push("randomize_color", target: @myself)} - /> + <.input_wrapper form={f} field={:hub_emoji} class="flex flex-col space-y-1"> +
Emoji
+ <.emoji_input id="fly-emoji-input" form={f} field={:hub_emoji} /> @@ -86,7 +81,7 @@ defmodule LivebookWeb.Hub.New.FlyComponent do case FlyClient.fetch_apps(token) do {:ok, apps} -> opts = select_options(apps) - base = %Fly{access_token: token, hub_color: HexColor.random()} + base = %Fly{access_token: token, hub_emoji: "🚀"} changeset = Fly.change_hub(base) {:noreply, @@ -103,10 +98,6 @@ defmodule LivebookWeb.Hub.New.FlyComponent do end end - def handle_event("randomize_color", _, socket) do - handle_event("validate", %{"fly" => %{"hub_color" => HexColor.random()}}, socket) - end - def handle_event("save", %{"fly" => params}, socket) do if socket.assigns.changeset.valid? do case Fly.create_hub(socket.assigns.selected_app, params) do diff --git a/lib/livebook_web/live/layout_helpers.ex b/lib/livebook_web/live/layout_helpers.ex index bd31de2a8..e35926943 100644 --- a/lib/livebook_web/live/layout_helpers.ex +++ b/lib/livebook_web/live/layout_helpers.ex @@ -5,6 +5,7 @@ defmodule LivebookWeb.LayoutHelpers do import LivebookWeb.UserHelpers alias Phoenix.LiveView.JS + alias Livebook.Hubs.Provider alias LivebookWeb.Router.Helpers, as: Routes @doc """ @@ -165,15 +166,9 @@ defmodule LivebookWeb.LayoutHelpers do end defp sidebar_link(assigns) do - assigns = assign_new(assigns, :icon_style, fn -> nil end) - ~H""" <%= live_redirect to: @to, class: "h-7 flex items-center hover:text-white #{sidebar_link_text_color(@to, @current)} border-l-4 #{sidebar_link_border_color(@to, @current)} hover:border-white" do %> - <.remix_icon - icon={@icon} - class="text-lg leading-6 w-[56px] flex justify-center" - style={@icon_style} - /> + <.remix_icon icon={@icon} class="text-lg leading-6 w-[56px] flex justify-center" /> <%= @title %> @@ -181,6 +176,28 @@ defmodule LivebookWeb.LayoutHelpers do """ end + defp sidebar_hub_link(assigns) do + ~H""" + <%= live_redirect to: @to, class: "h-7 flex items-center hover:text-white #{sidebar_link_text_color(@to, @current)} border-l-4 #{sidebar_link_border_color(@to, @current)} hover:border-white" do %> +
+ + <%= @hub.emoji %> + + <%= if Provider.connect(@hub.provider) do %> +
+ <% end %> + +
+ + <%= @hub.name %> + + <% end %> + """ + end + defp hub_section(assigns) do ~H""" <%= if Livebook.Config.feature_flag_enabled?(:hub) do %> @@ -191,10 +208,8 @@ defmodule LivebookWeb.LayoutHelpers do
<%= for hub <- @hubs do %> - <.sidebar_link - title={hub.name} - icon="checkbox-blank-circle-fill" - icon_style={"color: #{hub.color}"} + <.sidebar_hub_link + hub={hub} to={Routes.hub_path(@socket, :edit, hub.id)} current={@current_page} /> diff --git a/lib/livebook_web/live/session_live.ex b/lib/livebook_web/live/session_live.ex index 1d4a3cc06..3941bed01 100644 --- a/lib/livebook_web/live/session_live.ex +++ b/lib/livebook_web/live/session_live.ex @@ -26,8 +26,7 @@ defmodule LivebookWeb.SessionLive do Session.subscribe(session_id) Secrets.subscribe() - # TODO: Move this to Hubs.subscribe([:secrets]) and rename all "enterprise" to "hubs" - EnterpriseClient.subscribe() + Hubs.subscribe(:secrets) {data, client_id} else @@ -64,7 +63,7 @@ defmodule LivebookWeb.SessionLive do autofocus_cell_id: autofocus_cell_id(data.notebook), page_title: get_page_title(data.notebook.name), livebook_secrets: Secrets.fetch_secrets() |> Map.new(&{&1.name, &1.value}), - enterprise_secrets: fetch_enterprise_secrets(), + hub_secrets: get_hub_secrets(), select_secret_ref: nil, select_secret_options: nil ) @@ -186,7 +185,7 @@ defmodule LivebookWeb.SessionLive do <.secrets_list data_view={@data_view} livebook_secrets={@livebook_secrets} - enterprise_secrets={@enterprise_secrets} + hub_secrets={@hub_secrets} session={@session} socket={@socket} /> @@ -739,13 +738,13 @@ defmodule LivebookWeb.SessionLive do <%= if Livebook.Config.feature_flag_enabled?(:hub) do %>

- Enterprise secrets + Hub secrets

Available in all sessions
- <%= for {secret_name, secret_value} <- Enum.sort(@enterprise_secrets) do %> + <%= for {secret_name, secret_value} <- Enum.sort(@hub_secrets) do %>
assign(enterprise_secrets: fetch_enterprise_secrets()) + |> assign(hub_secrets: get_hub_secrets()) |> put_flash(:info, "A new secret has been created on your Livebook Enterprise")} end def handle_info({:secret_updated, %Secrets.Secret{}}, socket) do {:noreply, socket - |> assign(enterprise_secrets: fetch_enterprise_secrets()) + |> assign(hub_secrets: get_hub_secrets()) |> put_flash(:info, "An existing secret has been updated on your Livebook Enterprise")} end @@ -2298,7 +2297,7 @@ defmodule LivebookWeb.SessionLive do secret in secrets end - defp fetch_enterprise_secrets do + defp get_hub_secrets do for connected_hub <- Hubs.get_connected_hubs(), secret <- EnterpriseClient.list_cached_secrets(connected_hub.pid), into: %{}, diff --git a/test/livebook/hubs/enterprise_client_test.exs b/test/livebook/hubs/enterprise_client_test.exs index c801b4d76..0da621bde 100644 --- a/test/livebook/hubs/enterprise_client_test.exs +++ b/test/livebook/hubs/enterprise_client_test.exs @@ -6,7 +6,7 @@ defmodule Livebook.Hubs.EnterpriseClientTest do alias Livebook.Secrets.Secret setup do - EnterpriseClient.subscribe() + Livebook.Hubs.subscribe([:connection, :secrets]) :ok end @@ -15,21 +15,21 @@ defmodule Livebook.Hubs.EnterpriseClientTest do enterprise = build(:enterprise, url: url, token: token) EnterpriseClient.start_link(enterprise) - assert_receive {:connect, :ok, :connected} + assert_receive :hub_connected end test "rejects the websocket with invalid address", %{token: token} do enterprise = build(:enterprise, url: "http://localhost:9999", token: token) EnterpriseClient.start_link(enterprise) - assert_receive {:connect, :error, "connection refused"} + assert_receive {:connection_error, "connection refused"} end test "rejects the web socket connection with invalid credentials", %{url: url} do enterprise = build(:enterprise, url: url, token: "foo") EnterpriseClient.start_link(enterprise) - assert_receive {:connect, :error, reason} + assert_receive {:connection_error, reason} assert reason =~ "the given token is invalid" end end @@ -38,8 +38,7 @@ defmodule Livebook.Hubs.EnterpriseClientTest do setup %{url: url, token: token} do enterprise = build(:enterprise, url: url, token: token) EnterpriseClient.start_link(enterprise) - - assert_receive {:connect, :ok, :connected} + assert_receive :hub_connected :ok end diff --git a/test/livebook/hubs/provider_test.exs b/test/livebook/hubs/provider_test.exs index 321afd4c5..c492d719b 100644 --- a/test/livebook/hubs/provider_test.exs +++ b/test/livebook/hubs/provider_test.exs @@ -10,7 +10,7 @@ defmodule Livebook.Hubs.ProviderTest do assert Provider.normalize(fly) == %Metadata{ id: fly.id, name: fly.hub_name, - color: fly.hub_color, + emoji: fly.hub_emoji, provider: fly } end diff --git a/test/livebook/hubs_test.exs b/test/livebook/hubs_test.exs index e9aeed9d0..f68a3f1d0 100644 --- a/test/livebook/hubs_test.exs +++ b/test/livebook/hubs_test.exs @@ -23,7 +23,7 @@ defmodule Livebook.HubsTest do assert Hubs.get_metadatas() == [ %Hubs.Metadata{ id: "fly-livebook", - color: fly.hub_color, + emoji: fly.hub_emoji, name: fly.hub_name, provider: fly } @@ -60,9 +60,9 @@ defmodule Livebook.HubsTest do test "save_hub/1 updates hub" do fly = insert_hub(:fly, id: "fly-foo2") - Hubs.save_hub(%{fly | hub_color: "#FFFFFF"}) + Hubs.save_hub(%{fly | hub_emoji: "🐈"}) refute Hubs.fetch_hub!("fly-foo2") == fly - assert Hubs.fetch_hub!("fly-foo2").hub_color == "#FFFFFF" + assert Hubs.fetch_hub!("fly-foo2").hub_emoji == "🐈" end end diff --git a/test/livebook_web/live/hub/edit_live_test.exs b/test/livebook_web/live/hub/edit_live_test.exs index 3662e619f..abd3452c7 100644 --- a/test/livebook_web/live/hub/edit_live_test.exs +++ b/test/livebook_web/live/hub/edit_live_test.exs @@ -40,7 +40,7 @@ defmodule LivebookWeb.Hub.EditLiveTest do attrs = %{ "hub_name" => "Personal Hub", - "hub_color" => "#FF00FF" + "hub_emoji" => "🐈" } view @@ -59,7 +59,7 @@ defmodule LivebookWeb.Hub.EditLiveTest do assert render(view) =~ "Hub updated successfully" - assert_hub(view, conn, %{hub | hub_color: attrs["hub_color"], hub_name: attrs["hub_name"]}) + assert_hub(view, conn, %{hub | hub_emoji: attrs["hub_emoji"], hub_name: attrs["hub_name"]}) refute Hubs.fetch_hub!(hub.id) == hub end @@ -195,7 +195,7 @@ defmodule LivebookWeb.Hub.EditLiveTest do hub = insert_hub(:enterprise) {:ok, view, _html} = live(conn, Routes.hub_path(conn, :edit, hub.id)) - attrs = %{"hub_color" => "#FF00FF"} + attrs = %{"hub_emoji" => "🐈"} view |> element("#enterprise-form") @@ -213,7 +213,7 @@ defmodule LivebookWeb.Hub.EditLiveTest do assert render(view) =~ "Hub updated successfully" - assert_hub(view, conn, %{hub | hub_color: attrs["hub_color"]}) + assert_hub(view, conn, %{hub | hub_emoji: attrs["hub_emoji"]}) refute Hubs.fetch_hub!(hub.id) == hub end end @@ -221,7 +221,7 @@ defmodule LivebookWeb.Hub.EditLiveTest do defp assert_hub(view, conn, hub) do hubs_html = view |> element("#hubs") |> render() - assert hubs_html =~ ~s/style="color: #{hub.hub_color}"/ + assert hubs_html =~ hub.hub_emoji assert hubs_html =~ Routes.hub_path(conn, :edit, hub.id) assert hubs_html =~ hub.hub_name end diff --git a/test/livebook_web/live/hub/new/enterprise_component_test.exs b/test/livebook_web/live/hub/new/enterprise_component_test.exs index 22c5968bf..e2a9a5f0e 100644 --- a/test/livebook_web/live/hub/new/enterprise_component_test.exs +++ b/test/livebook_web/live/hub/new/enterprise_component_test.exs @@ -37,7 +37,7 @@ defmodule LivebookWeb.Hub.New.EnterpriseComponentTest do "url" => url, "token" => token, "hub_name" => "Enterprise", - "hub_color" => "#FF00FF" + "hub_emoji" => "🐈" } view @@ -58,7 +58,7 @@ defmodule LivebookWeb.Hub.New.EnterpriseComponentTest do assert render(view) =~ "Hub added successfully" hubs_html = view |> element("#hubs") |> render() - assert hubs_html =~ ~s/style="color: #FF00FF"/ + assert hubs_html =~ "🐈" assert hubs_html =~ "/hub/enterprise-#{id}" assert hubs_html =~ "Enterprise" end @@ -94,8 +94,13 @@ defmodule LivebookWeb.Hub.New.EnterpriseComponentTest do stop_new_instance(name) end - test "fails to create existing hub", %{conn: conn, url: url, token: token} do - node = EnterpriseServer.get_node() + test "fails to create existing hub", %{test: name, conn: conn} do + start_new_instance(name) + + node = EnterpriseServer.get_node(name) + url = EnterpriseServer.url(name) + token = EnterpriseServer.token(name) + id = :erpc.call(node, Enterprise.Integration, :fetch_env!, []) user = :erpc.call(node, Enterprise.Integration, :create_user, []) @@ -135,7 +140,7 @@ defmodule LivebookWeb.Hub.New.EnterpriseComponentTest do "url" => url, "token" => token, "hub_name" => "Enterprise", - "hub_color" => "#FFFFFF" + "hub_emoji" => "🐈" } view @@ -151,11 +156,13 @@ defmodule LivebookWeb.Hub.New.EnterpriseComponentTest do |> render_submit(%{"enterprise" => attrs}) =~ "already exists" hubs_html = view |> element("#hubs") |> render() - assert hubs_html =~ ~s/style="color: #{hub.hub_color}"/ + assert hubs_html =~ hub.hub_emoji assert hubs_html =~ Routes.hub_path(conn, :edit, hub.id) assert hubs_html =~ hub.hub_name assert Hubs.fetch_hub!(hub.id) == hub + after + stop_new_instance(name) end end diff --git a/test/livebook_web/live/hub/new_live_test.exs b/test/livebook_web/live/hub/new_live_test.exs index 45adc3b58..8c0c20e47 100644 --- a/test/livebook_web/live/hub/new_live_test.exs +++ b/test/livebook_web/live/hub/new_live_test.exs @@ -36,7 +36,7 @@ defmodule LivebookWeb.Hub.NewLiveTest do "access_token" => "dummy access token", "application_id" => "123456789", "hub_name" => "My Foo Hub", - "hub_color" => "#FF00FF" + "hub_emoji" => "🐈" } view @@ -55,17 +55,11 @@ defmodule LivebookWeb.Hub.NewLiveTest do assert render(view) =~ "Hub added successfully" - assert view - |> element("#hubs") - |> render() =~ ~s/style="color: #FF00FF"/ + hubs_html = view |> element("#hubs") |> render() - assert view - |> element("#hubs") - |> render() =~ "/hub/fly-123456789" - - assert view - |> element("#hubs") - |> render() =~ "My Foo Hub" + assert hubs_html =~ "🐈" + assert hubs_html =~ "/hub/fly-123456789" + assert hubs_html =~ "My Foo Hub" end test "fails to create existing hub", %{conn: conn} do @@ -87,7 +81,7 @@ defmodule LivebookWeb.Hub.NewLiveTest do "access_token" => "dummy access token", "application_id" => "foo", "hub_name" => "My Foo Hub", - "hub_color" => "#FF00FF" + "hub_emoji" => "🐈" } view @@ -102,18 +96,7 @@ defmodule LivebookWeb.Hub.NewLiveTest do |> element("#fly-form") |> render_submit(%{"fly" => attrs}) =~ "already exists" - assert view - |> element("#hubs") - |> render() =~ ~s/style="color: #{hub.hub_color}"/ - - assert view - |> element("#hubs") - |> render() =~ Routes.hub_path(conn, :edit, hub.id) - - assert view - |> element("#hubs") - |> render() =~ hub.hub_name - + assert_hub(view, conn, hub) assert Hubs.fetch_hub!(hub.id) == hub end end @@ -177,4 +160,12 @@ defmodule LivebookWeb.Hub.NewLiveTest do %{"data" => %{"app" => app}} end + + defp assert_hub(view, conn, hub) do + hubs_html = view |> element("#hubs") |> render() + + assert hubs_html =~ hub.hub_emoji + assert hubs_html =~ Routes.hub_path(conn, :edit, hub.id) + assert hubs_html =~ hub.hub_name + end end diff --git a/test/livebook_web/live/session_live/secrets_component_test.exs b/test/livebook_web/live/session_live/secrets_component_test.exs index 90a8adc03..a3179a8f8 100644 --- a/test/livebook_web/live/session_live/secrets_component_test.exs +++ b/test/livebook_web/live/session_live/secrets_component_test.exs @@ -9,7 +9,8 @@ defmodule LivebookWeb.SessionLive.SecretsComponentTest do describe "enterprise" do setup %{url: url, token: token} do - id = Livebook.Utils.random_id() + node = EnterpriseServer.get_node() + id = :erpc.call(node, Enterprise.Integration, :fetch_env!, []) Livebook.Hubs.delete_hub("enterprise-#{id}") enterprise = @@ -21,8 +22,7 @@ defmodule LivebookWeb.SessionLive.SecretsComponentTest do ) {:ok, session} = Sessions.create_session(notebook: Livebook.Notebook.new()) - Livebook.Hubs.EnterpriseClient.subscribe() - Livebook.Hubs.connect_hubs() + Livebook.Hubs.subscribe(:secrets) on_exit(fn -> Session.close(session.pid) diff --git a/test/support/factory.ex b/test/support/factory.ex index 94c5950b2..1a117d847 100644 --- a/test/support/factory.ex +++ b/test/support/factory.ex @@ -17,7 +17,7 @@ defmodule Livebook.Factory do %Livebook.Hubs.Fly{ id: "fly-foo-bar-baz", hub_name: "My Personal Hub", - hub_color: "#FF00FF", + hub_emoji: "🚀", access_token: Livebook.Utils.random_cookie(), organization_id: Livebook.Utils.random_id(), organization_type: "PERSONAL", @@ -36,7 +36,7 @@ defmodule Livebook.Factory do %Livebook.Hubs.Enterprise{ id: "enterprise-#{id}", hub_name: "Enterprise", - hub_color: "#FF0000", + hub_emoji: "🏭", external_id: id, token: Livebook.Utils.random_cookie(), url: "http://localhost"