Packages
livebook
0.8.0
0.19.8
0.19.7
0.19.6
0.19.5
0.19.4
0.19.3
0.19.2
0.19.1
0.19.0
0.18.6
0.18.5
0.18.4
0.18.3
0.18.2
0.18.1
0.18.0
0.17.3
0.17.2
0.17.1
0.17.0
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.7
0.14.6
0.14.5
0.14.4
0.14.3
0.14.2
0.14.1
0.14.0
0.14.0-rc.1
0.14.0-rc.0
0.13.3
0.13.2
0.13.1
0.13.0
0.12.1
0.12.0
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.0
0.9.3
0.9.2
0.9.1
0.9.0
0.8.2
0.8.1
0.8.0
0.7.2
0.7.1
0.7.0
0.6.3
0.6.2
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
0.4.1
0.4.0
0.3.2
0.3.1
0.3.0
0.2.3
0.2.2
0.2.1
0.2.0
0.1.2
0.1.1
0.1.0
Automate code & data workflows with interactive notebooks
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/livebook_web/live/output/frame_component.ex
defmodule LivebookWeb.Output.FrameComponent do
use LivebookWeb, :live_component
@impl true
def mount(socket) do
{:ok, assign(socket, counter: 0, output_count: 0, persistent_id_map: %{})}
end
@impl true
def update(assigns, socket) do
{update_type, assigns} = Map.pop(assigns, :update_type, nil)
{outputs, assigns} = Map.pop!(assigns, :outputs)
socket = assign(socket, assigns)
socket =
if socket.assigns.counter == 0 do
assign(socket,
counter: 1,
output_count: length(outputs),
persistent_id_map: map_idx_to_persistent_id(outputs, socket.assigns.id)
)
else
socket
end
socket =
case update_type do
nil ->
assign(socket, outputs: outputs)
:replace ->
prev_output_count = socket.assigns.output_count
prev_persistent_id_map = socket.assigns.persistent_id_map
output_count = length(outputs)
persistent_id_map = map_idx_to_persistent_id(outputs, socket.assigns.id)
socket =
assign(socket,
outputs: outputs,
output_count: output_count,
persistent_id_map: persistent_id_map
)
less_outputs? = prev_output_count > output_count
appended_outputs? = prev_output_count > map_size(prev_persistent_id_map)
# If there are outputs that we need to remove, increase the counter.
# Otherwise we reuse DOM element ids via persistent_id_map
if less_outputs? or appended_outputs? do
update(socket, :counter, &(&1 + 1))
else
socket
end
:append ->
socket
|> update(:outputs, &(outputs ++ &1))
|> update(:output_count, &(length(outputs) + &1))
end
{:ok, socket}
end
defp map_idx_to_persistent_id(outputs, root_id) do
outputs
|> Enum.with_index()
|> Map.new(fn {{output_idx, _}, idx} -> {output_idx, "#{root_id}-#{idx}"} end)
end
@impl true
def render(assigns) do
~H"""
<div id={"frame-output-#{@id}"}>
<%= if @output_count == 0 do %>
<div class="text-gray-300 p-4 rounded-lg border border-gray-200">
Empty output frame
</div>
<% else %>
<div id={"frame-outputs-#{@id}-#{@counter}"} phx-update="append">
<LivebookWeb.Output.outputs
outputs={@outputs}
dom_id_map={@persistent_id_map}
socket={@socket}
session_id={@session_id}
input_values={@input_values}
client_id={@client_id}
/>
</div>
<% end %>
</div>
"""
end
end