From ace64eab37d8124648929a97898906d1410ed9cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Per=C5=BCy=C5=82o?= Date: Mon, 1 Nov 2021 16:04:11 +0100 Subject: [PATCH] Add show/hide button for password inputs #566 (#664) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added visibility toggle for password cell * Formatted code * Moved password toggle to separate component * Adjusted to review * Added password toggle for add filesystem component * Update lib/livebook_web/helpers.ex Co-authored-by: Jonatan Kłosko --- assets/js/app.js | 2 + assets/js/password_toggle/index.js | 38 +++++++++++++++++++ lib/livebook_web/helpers.ex | 29 ++++++++++++++ .../live/session_live/cell_component.ex | 23 +++++++++-- .../add_file_system_component.ex | 8 +++- 5 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 assets/js/password_toggle/index.js diff --git a/assets/js/app.js b/assets/js/app.js index 5fd56eefe..5d1910107 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -25,6 +25,7 @@ import MarkdownRenderer from "./markdown_renderer"; import Highlight from "./highlight"; import ClipCopy from "./clip_copy"; import DragAndDrop from "./darg_and_drop"; +import PasswordToggle from "./password_toggle"; import morphdomCallbacks from "./morphdom_callbacks"; import { loadUserData } from "./lib/user"; @@ -43,6 +44,7 @@ const hooks = { Highlight, ClipCopy, DragAndDrop, + PasswordToggle, }; const csrfToken = document diff --git a/assets/js/password_toggle/index.js b/assets/js/password_toggle/index.js new file mode 100644 index 000000000..225a02814 --- /dev/null +++ b/assets/js/password_toggle/index.js @@ -0,0 +1,38 @@ +/** + * A hook used to toggle password's input visibility via icon button. + */ + +const VISIBLE_ICON = "ri-eye-off-line"; +const OBSCURED_ICON = "ri-eye-line"; + +const PasswordToggle = { + mounted() { + this.visible = false; + + this.input = this.el.querySelector("input"); + this.iconButton = this.el.querySelector("i"); + + this.iconButton.addEventListener("click", () => { + this.visible = !this.visible; + this._updateDOM(); + }); + }, + + updated() { + this._updateDOM(); + }, + + _updateDOM() { + if (this.visible) { + this.input.type = "text"; + this.iconButton.classList.remove(OBSCURED_ICON); + this.iconButton.classList.add(VISIBLE_ICON); + } else { + this.input.type = "password"; + this.iconButton.classList.remove(VISIBLE_ICON); + this.iconButton.classList.add(OBSCURED_ICON); + } + }, +}; + +export default PasswordToggle; diff --git a/lib/livebook_web/helpers.ex b/lib/livebook_web/helpers.ex index 7d409f3df..183e1eda2 100644 --- a/lib/livebook_web/helpers.ex +++ b/lib/livebook_web/helpers.ex @@ -246,6 +246,35 @@ defmodule LivebookWeb.Helpers do """ end + @doc """ + Renders a wrapper around password input + with an added visibility toggle button. + + The toggle switches the input's type between `password` + and `text`. + + ## Examples + + <.with_password_toggle id="input-id"> + + + """ + def with_password_toggle(assigns) do + ~H""" +
+ + <%= render_block(@inner_block) %> + +
+ """ + end + defdelegate ansi_string_to_html(string), to: LivebookWeb.Helpers.ANSI defdelegate ansi_string_to_html_lines(string), to: LivebookWeb.Helpers.ANSI diff --git a/lib/livebook_web/live/session_live/cell_component.ex b/lib/livebook_web/live/session_live/cell_component.ex index c8b239de2..1f20edcf1 100644 --- a/lib/livebook_web/live/session_live/cell_component.ex +++ b/lib/livebook_web/live/session_live/cell_component.ex @@ -1,6 +1,7 @@ defmodule LivebookWeb.SessionLive.CellComponent do use LivebookWeb, :live_component + @impl true def render(assigns) do ~H"""
@@ -51,7 +52,7 @@ defmodule LivebookWeb.SessionLive.CellComponent do """ end - def render_cell(%{cell_view: %{type: :elixir}} = assigns) do + defp render_cell(%{cell_view: %{type: :elixir}} = assigns) do ~H"""
@@ -106,7 +107,7 @@ defmodule LivebookWeb.SessionLive.CellComponent do """ end - def render_cell(%{cell_view: %{type: :input}} = assigns) do + defp render_cell(%{cell_view: %{type: :input}} = assigns) do ~H"""
@@ -200,6 +201,22 @@ defmodule LivebookWeb.SessionLive.CellComponent do """ end + defp cell_input(%{cell_view: %{input_type: :password}} = assigns) do + ~H""" + <.with_password_toggle id={@cell_view.id}> + + + """ + end + defp cell_input(assigns) do ~H"""
Access Key ID
- <%= text_input f, :access_key_id, value: @data["access_key_id"], class: "input", type: "password" %> + <.with_password_toggle id="access-key"> + <%= text_input f, :access_key_id, value: @data["access_key_id"], class: "input", type: "password" %> +
Secret Access Key
- <%= text_input f, :secret_access_key, value: @data["secret_access_key"], class: "input", type: "password" %> + <.with_password_toggle id="secret-access-key"> + <%= text_input f, :secret_access_key, value: @data["secret_access_key"], class: "input", type: "password" %> +