Add :debounce to input outputs when missing (#2228)

This commit is contained in:
Jonatan Kłosko 2023-09-26 10:38:15 +07:00 committed by GitHub
parent edc09cd386
commit 05418db0c6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 75 additions and 22 deletions

View file

@ -298,28 +298,33 @@ defprotocol Livebook.Runtime do
%{ %{
type: :text, type: :text,
default: String.t(), default: String.t(),
label: String.t() label: String.t(),
debounce: :blur | non_neg_integer()
} }
| %{ | %{
type: :textarea, type: :textarea,
default: String.t(), default: String.t(),
label: String.t(), label: String.t(),
debounce: :blur | non_neg_integer(),
monospace: boolean() monospace: boolean()
} }
| %{ | %{
type: :password, type: :password,
default: String.t(), default: String.t(),
label: String.t() label: String.t(),
debounce: :blur | non_neg_integer()
} }
| %{ | %{
type: :number, type: :number,
default: number() | nil, default: number() | nil,
label: String.t() label: String.t(),
debounce: :blur | non_neg_integer()
} }
| %{ | %{
type: :url, type: :url,
default: String.t() | nil, default: String.t() | nil,
label: String.t() label: String.t(),
debounce: :blur | non_neg_integer()
} }
| %{ | %{
type: :select, type: :select,
@ -336,6 +341,7 @@ defprotocol Livebook.Runtime do
type: :range, type: :range,
default: number(), default: number(),
label: String.t(), label: String.t(),
debounce: :blur | non_neg_integer(),
min: number(), min: number(),
max: number(), max: number(),
step: number() step: number()
@ -364,7 +370,8 @@ defprotocol Livebook.Runtime do
| %{ | %{
type: :color, type: :color,
default: String.t(), default: String.t(),
label: String.t() label: String.t(),
debounce: :blur | non_neg_integer()
} }
| %{ | %{
type: :image, type: :image,

View file

@ -2886,39 +2886,70 @@ defmodule Livebook.Session do
end end
end end
# Maps legacy outputs and adds missing attributes # Normalizes output to match the most recent specification.
#
# Rewrites legacy output formats and adds defaults for newly introduced
# attributes that are missing.
defp normalize_runtime_output(output)
defp normalize_runtime_output(%{type: :input, attrs: attrs} = output)
when attrs.type in [:text, :textarea, :password, :number, :url, :range, :color] and
not is_map_key(attrs, :debounce) do
put_in(output.attrs[:debounce], :blur)
|> normalize_runtime_output()
end
# Traverse composite outputs
defp normalize_runtime_output(output) when output.type in [:frame, :tabs, :grid] do
outputs = Enum.map(output.outputs, &normalize_runtime_output/1)
%{output | outputs: outputs}
end
defp normalize_runtime_output(%{type: :frame_update} = output) do
{update_type, new_outputs} = output.update
new_outputs = Enum.map(new_outputs, &normalize_runtime_output/1)
%{output | update: {update_type, new_outputs}}
end
defp normalize_runtime_output(output) when is_map(output), do: output defp normalize_runtime_output(output) when is_map(output), do: output
# Rewrite tuples to maps for backward compatibility with Kino <= 0.10.0
defp normalize_runtime_output(:ignored) do defp normalize_runtime_output(:ignored) do
%{type: :ignored} %{type: :ignored}
|> normalize_runtime_output()
end end
# Rewrite tuples to maps for backward compatibility with Kino <= 0.10.0
defp normalize_runtime_output({:text, text}) do defp normalize_runtime_output({:text, text}) do
%{type: :terminal_text, text: text, chunk: false} %{type: :terminal_text, text: text, chunk: false}
|> normalize_runtime_output()
end end
defp normalize_runtime_output({:plain_text, text}) do defp normalize_runtime_output({:plain_text, text}) do
%{type: :plain_text, text: text, chunk: false} %{type: :plain_text, text: text, chunk: false}
|> normalize_runtime_output()
end end
defp normalize_runtime_output({:markdown, text}) do defp normalize_runtime_output({:markdown, text}) do
%{type: :markdown, text: text, chunk: false} %{type: :markdown, text: text, chunk: false}
|> normalize_runtime_output()
end end
defp normalize_runtime_output({:image, content, mime_type}) do defp normalize_runtime_output({:image, content, mime_type}) do
%{type: :image, content: content, mime_type: mime_type} %{type: :image, content: content, mime_type: mime_type}
|> normalize_runtime_output()
end end
# Rewrite older output format for backward compatibility with Kino <= 0.5.2 # Rewrite older output format for backward compatibility with Kino <= 0.5.2
defp normalize_runtime_output({:js, %{ref: ref, pid: pid, assets: assets, export: export}}) do defp normalize_runtime_output({:js, %{ref: ref, pid: pid, assets: assets, export: export}}) do
normalize_runtime_output( {:js, %{js_view: %{ref: ref, pid: pid, assets: assets}, export: export}}
{:js, %{js_view: %{ref: ref, pid: pid, assets: assets}, export: export}} |> normalize_runtime_output()
)
end end
defp normalize_runtime_output({:js, info}) do defp normalize_runtime_output({:js, info}) do
%{type: :js, js_view: info.js_view, export: info.export} %{type: :js, js_view: info.js_view, export: info.export}
|> normalize_runtime_output()
end end
defp normalize_runtime_output({:frame, outputs, %{ref: ref, type: :default} = info}) do defp normalize_runtime_output({:frame, outputs, %{ref: ref, type: :default} = info}) do
@ -2928,6 +2959,7 @@ defmodule Livebook.Session do
outputs: Enum.map(outputs, &normalize_runtime_output/1), outputs: Enum.map(outputs, &normalize_runtime_output/1),
placeholder: Map.get(info, :placeholder, true) placeholder: Map.get(info, :placeholder, true)
} }
|> normalize_runtime_output()
end end
defp normalize_runtime_output({:frame, outputs, %{ref: ref, type: :replace}}) do defp normalize_runtime_output({:frame, outputs, %{ref: ref, type: :replace}}) do
@ -2936,6 +2968,7 @@ defmodule Livebook.Session do
ref: ref, ref: ref,
update: {:replace, Enum.map(outputs, &normalize_runtime_output/1)} update: {:replace, Enum.map(outputs, &normalize_runtime_output/1)}
} }
|> normalize_runtime_output()
end end
defp normalize_runtime_output({:frame, outputs, %{ref: ref, type: :append}}) do defp normalize_runtime_output({:frame, outputs, %{ref: ref, type: :append}}) do
@ -2944,10 +2977,12 @@ defmodule Livebook.Session do
ref: ref, ref: ref,
update: {:append, Enum.map(outputs, &normalize_runtime_output/1)} update: {:append, Enum.map(outputs, &normalize_runtime_output/1)}
} }
|> normalize_runtime_output()
end end
defp normalize_runtime_output({:tabs, outputs, %{labels: labels}}) do defp normalize_runtime_output({:tabs, outputs, %{labels: labels}}) do
%{type: :tabs, outputs: Enum.map(outputs, &normalize_runtime_output/1), labels: labels} %{type: :tabs, outputs: Enum.map(outputs, &normalize_runtime_output/1), labels: labels}
|> normalize_runtime_output()
end end
defp normalize_runtime_output({:grid, outputs, info}) do defp normalize_runtime_output({:grid, outputs, info}) do
@ -2958,6 +2993,7 @@ defmodule Livebook.Session do
gap: Map.get(info, :gap, 8), gap: Map.get(info, :gap, 8),
boxed: Map.get(info, :boxed, false) boxed: Map.get(info, :boxed, false)
} }
|> normalize_runtime_output()
end end
defp normalize_runtime_output({:input, attrs}) do defp normalize_runtime_output({:input, attrs}) do
@ -2970,6 +3006,7 @@ defmodule Livebook.Session do
end end
Map.merge(fields, %{type: :input, attrs: attrs}) Map.merge(fields, %{type: :input, attrs: attrs})
|> normalize_runtime_output()
end end
defp normalize_runtime_output({:control, attrs}) do defp normalize_runtime_output({:control, attrs}) do
@ -2992,6 +3029,7 @@ defmodule Livebook.Session do
end end
Map.merge(fields, %{type: :control, attrs: attrs}) Map.merge(fields, %{type: :control, attrs: attrs})
|> normalize_runtime_output()
end end
defp normalize_runtime_output({:error, message, type}) do defp normalize_runtime_output({:error, message, type}) do
@ -3002,9 +3040,11 @@ defmodule Livebook.Session do
end end
%{type: :error, message: message, context: context} %{type: :error, message: message, context: context}
|> normalize_runtime_output()
end end
defp normalize_runtime_output(other) do defp normalize_runtime_output(other) do
%{type: :unknown, output: other} %{type: :unknown, output: other}
|> normalize_runtime_output()
end end
end end

View file

@ -169,7 +169,7 @@ defmodule LivebookWeb.Output.InputComponent do
class="input-range" class="input-range"
name="html_value" name="html_value"
value={@value} value={@value}
phx-debounce={@attrs[:debounce] || "blur"} phx-debounce={@attrs.debounce}
phx-target={@myself} phx-target={@myself}
spellcheck="false" spellcheck="false"
autocomplete="off" autocomplete="off"
@ -190,7 +190,7 @@ defmodule LivebookWeb.Output.InputComponent do
class={["input min-h-[38px] max-h-[300px] tiny-scrollbar", @attrs.monospace && "font-mono"]} class={["input min-h-[38px] max-h-[300px] tiny-scrollbar", @attrs.monospace && "font-mono"]}
name="html_value" name="html_value"
phx-hook="TextareaAutosize" phx-hook="TextareaAutosize"
phx-debounce={@attrs[:debounce] || "blur"} phx-debounce={@attrs.debounce}
phx-target={@myself} phx-target={@myself}
spellcheck="false" spellcheck="false"
><%= [?\n, @value] %></textarea> ><%= [?\n, @value] %></textarea>
@ -206,7 +206,7 @@ defmodule LivebookWeb.Output.InputComponent do
class="input w-auto bg-gray-50" class="input w-auto bg-gray-50"
name="html_value" name="html_value"
value={@value} value={@value}
phx-debounce={@attrs[:debounce] || "blur"} phx-debounce={@attrs.debounce}
phx-target={@myself} phx-target={@myself}
spellcheck="false" spellcheck="false"
autocomplete="off" autocomplete="off"
@ -241,7 +241,7 @@ defmodule LivebookWeb.Output.InputComponent do
class="input w-auto invalid:input--error" class="input w-auto invalid:input--error"
name="html_value" name="html_value"
value={to_string(@value)} value={to_string(@value)}
phx-debounce={@attrs[:debounce] || "blur"} phx-debounce={@attrs.debounce}
phx-target={@myself} phx-target={@myself}
spellcheck="false" spellcheck="false"
autocomplete="off" autocomplete="off"

View file

@ -18,7 +18,7 @@ defmodule Livebook.Session.DataTest do
ref: "ref1", ref: "ref1",
id: "i1", id: "i1",
destination: nil, destination: nil,
attrs: %{type: :text, default: "hey", label: "Text"} attrs: %{type: :text, default: "hey", label: "Text", debounce: :blur}
} }
defp eval_meta(opts \\ []) do defp eval_meta(opts \\ []) do
@ -4510,7 +4510,7 @@ defmodule Livebook.Session.DataTest do
ref: "ref1", ref: "ref1",
id: "i1", id: "i1",
destination: nil, destination: nil,
attrs: %{type: :text, default: "hey", label: "Text"} attrs: %{type: :text, default: "hey", label: "Text", debounce: :blur}
} }
input2 = %{ input2 = %{
@ -4518,7 +4518,7 @@ defmodule Livebook.Session.DataTest do
ref: "ref2", ref: "ref2",
id: "i2", id: "i2",
destination: nil, destination: nil,
attrs: %{type: :text, default: "hey", label: "Text"} attrs: %{type: :text, default: "hey", label: "Text", debounce: :blur}
} }
data = data =

View file

@ -219,7 +219,7 @@ defmodule Livebook.SessionTest do
ref: "ref", ref: "ref",
id: "input1", id: "input1",
destination: :noop, destination: :noop,
attrs: %{type: :text, default: "hey", label: "Name"} attrs: %{type: :text, default: "hey", label: "Name", debounce: :blur}
} }
smart_cell = %{ smart_cell = %{
@ -1899,7 +1899,7 @@ defmodule Livebook.SessionTest do
ref: "ref", ref: "ref",
id: "input1", id: "input1",
destination: :noop, destination: :noop,
attrs: %{type: :text, default: "hey", label: "Name"} attrs: %{type: :text, default: "hey", label: "Name", debounce: :blur}
} }
send(session.pid, {:runtime_evaluation_output, cell_id, legacy_output}) send(session.pid, {:runtime_evaluation_output, cell_id, legacy_output})

View file

@ -518,7 +518,13 @@ defmodule LivebookWeb.SessionLiveTest do
ref: "ref1", ref: "ref1",
id: "input1", id: "input1",
destination: test, destination: test,
attrs: %{type: :textarea, default: "hey", label: "Name", monospace: false} attrs: %{
type: :textarea,
default: "hey",
label: "Name",
debounce: :blur,
monospace: false
}
} }
Session.subscribe(session.id) Session.subscribe(session.id)
@ -552,7 +558,7 @@ defmodule LivebookWeb.SessionLiveTest do
ref: "input_ref1", ref: "input_ref1",
id: "input1", id: "input1",
destination: test, destination: test,
attrs: %{type: :text, default: "initial", label: "Name"} attrs: %{type: :text, default: "initial", label: "Name", debounce: :blur}
} }
], ],
submit: "Send", submit: "Send",
@ -781,7 +787,7 @@ defmodule LivebookWeb.SessionLiveTest do
ref: "ref1", ref: "ref1",
id: "input1", id: "input1",
destination: test, destination: test,
attrs: %{type: :number, default: 1, label: "Input inside frame"} attrs: %{type: :number, default: 1, label: "Input inside frame", debounce: :blur}
} }
frame_update = %{ frame_update = %{