2021-11-09 03:45:30 +08:00
|
|
|
defmodule LivebookWeb.Output do
|
|
|
|
use Phoenix.Component
|
|
|
|
|
2022-01-26 04:55:24 +08:00
|
|
|
import LivebookWeb.Helpers
|
|
|
|
|
2022-01-17 20:24:59 +08:00
|
|
|
alias LivebookWeb.Output
|
|
|
|
|
2021-11-09 03:45:30 +08:00
|
|
|
@doc """
|
2021-11-26 01:43:42 +08:00
|
|
|
Renders a list of cell outputs.
|
2021-11-09 03:45:30 +08:00
|
|
|
"""
|
2021-11-26 01:43:42 +08:00
|
|
|
def outputs(assigns) do
|
|
|
|
~H"""
|
2022-01-17 03:37:00 +08:00
|
|
|
<%= for {idx, output} <- Enum.reverse(@outputs) do %>
|
2022-01-18 22:13:50 +08:00
|
|
|
<div class="max-w-full" id={"output-wrapper-#{@dom_id_map[idx] || idx}"}
|
2022-01-17 03:37:00 +08:00
|
|
|
data-element="output"
|
|
|
|
data-border={border?(output)}
|
|
|
|
data-wrapper={wrapper?(output)}>
|
|
|
|
<%= render_output(output, %{
|
|
|
|
id: "output-#{idx}",
|
|
|
|
socket: @socket,
|
|
|
|
session_id: @session_id,
|
|
|
|
runtime: @runtime,
|
2022-02-28 20:53:33 +08:00
|
|
|
cell_validity: @cell_validity,
|
2022-01-17 03:37:00 +08:00
|
|
|
input_values: @input_values
|
|
|
|
}) %>
|
|
|
|
</div>
|
|
|
|
<% end %>
|
2021-11-26 01:43:42 +08:00
|
|
|
"""
|
|
|
|
end
|
|
|
|
|
2022-01-17 03:37:00 +08:00
|
|
|
defp border?({:stdout, _text}), do: true
|
|
|
|
defp border?({:text, _text}), do: true
|
|
|
|
defp border?({:error, _message, _type}), do: true
|
|
|
|
defp border?(_output), do: false
|
2021-11-26 01:43:42 +08:00
|
|
|
|
2022-01-17 03:37:00 +08:00
|
|
|
defp wrapper?({:frame, _outputs, _info}), do: true
|
|
|
|
defp wrapper?(_output), do: false
|
2021-11-26 01:43:42 +08:00
|
|
|
|
2022-01-17 03:37:00 +08:00
|
|
|
defp render_output({:stdout, text}, %{id: id}) do
|
|
|
|
text = if(text == :__pruned__, do: nil, else: text)
|
2022-01-17 20:24:59 +08:00
|
|
|
live_component(Output.StdoutComponent, id: id, text: text, follow: true)
|
2021-11-09 03:45:30 +08:00
|
|
|
end
|
|
|
|
|
2021-11-26 01:43:42 +08:00
|
|
|
defp render_output({:text, text}, %{id: id}) do
|
2022-01-17 03:37:00 +08:00
|
|
|
assigns = %{id: id, text: text}
|
|
|
|
|
|
|
|
~H"""
|
2022-01-17 20:24:59 +08:00
|
|
|
<Output.TextComponent.render id={@id} content={@text} follow={false} />
|
2022-01-17 03:37:00 +08:00
|
|
|
"""
|
2021-11-09 03:45:30 +08:00
|
|
|
end
|
|
|
|
|
2021-11-26 01:43:42 +08:00
|
|
|
defp render_output({:markdown, markdown}, %{id: id}) do
|
2022-01-17 20:24:59 +08:00
|
|
|
live_component(Output.MarkdownComponent, id: id, content: markdown)
|
2021-11-09 03:45:30 +08:00
|
|
|
end
|
|
|
|
|
2021-11-26 01:43:42 +08:00
|
|
|
defp render_output({:image, content, mime_type}, %{id: id}) do
|
2022-01-17 03:37:00 +08:00
|
|
|
assigns = %{id: id, content: content, mime_type: mime_type}
|
|
|
|
|
|
|
|
~H"""
|
2022-01-17 20:24:59 +08:00
|
|
|
<Output.ImageComponent.render content={@content} mime_type={@mime_type} />
|
2022-01-17 03:37:00 +08:00
|
|
|
"""
|
2021-11-09 03:45:30 +08:00
|
|
|
end
|
|
|
|
|
2022-02-28 20:53:33 +08:00
|
|
|
defp render_output({:js, js_info}, %{id: id, session_id: session_id}) do
|
|
|
|
live_component(LivebookWeb.JSViewComponent,
|
|
|
|
id: id,
|
|
|
|
js_view: js_info.js_view,
|
|
|
|
session_id: session_id
|
|
|
|
)
|
2021-11-26 01:43:42 +08:00
|
|
|
end
|
|
|
|
|
2022-01-17 03:37:00 +08:00
|
|
|
defp render_output({:frame, outputs, _info}, %{
|
|
|
|
id: id,
|
|
|
|
input_values: input_values,
|
|
|
|
session_id: session_id
|
|
|
|
}) do
|
2022-01-17 20:24:59 +08:00
|
|
|
live_component(Output.FrameComponent,
|
2022-01-17 03:37:00 +08:00
|
|
|
id: id,
|
|
|
|
outputs: outputs,
|
|
|
|
session_id: session_id,
|
|
|
|
input_values: input_values
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
2021-11-26 01:43:42 +08:00
|
|
|
defp render_output({:input, attrs}, %{id: id, input_values: input_values}) do
|
2022-01-17 20:24:59 +08:00
|
|
|
live_component(Output.InputComponent, id: id, attrs: attrs, input_values: input_values)
|
2021-11-09 03:45:30 +08:00
|
|
|
end
|
|
|
|
|
2021-12-12 07:09:35 +08:00
|
|
|
defp render_output({:control, attrs}, %{id: id, input_values: input_values}) do
|
2022-01-17 20:24:59 +08:00
|
|
|
live_component(Output.ControlComponent, id: id, attrs: attrs, input_values: input_values)
|
2021-12-02 23:45:00 +08:00
|
|
|
end
|
|
|
|
|
2021-12-03 21:03:06 +08:00
|
|
|
defp render_output({:error, formatted, :runtime_restart_required}, %{
|
|
|
|
runtime: runtime,
|
2022-02-28 20:53:33 +08:00
|
|
|
cell_validity: cell_validity
|
2021-12-03 21:03:06 +08:00
|
|
|
})
|
2022-02-28 20:53:33 +08:00
|
|
|
when runtime != nil and cell_validity == :evaluated do
|
2021-11-09 03:45:30 +08:00
|
|
|
assigns = %{formatted: formatted, is_standalone: Livebook.Runtime.standalone?(runtime)}
|
|
|
|
|
|
|
|
~H"""
|
2022-02-18 06:37:14 +08:00
|
|
|
<div class="flex flex-col space-y-4" role="complementary" aria-label="runtime restart required">
|
2022-01-26 04:55:24 +08:00
|
|
|
<%= render_error(@formatted) %>
|
2022-01-17 03:37:00 +08:00
|
|
|
<%= if @is_standalone do %>
|
|
|
|
<div>
|
|
|
|
<button class="button-base button-gray" phx-click="restart_runtime">
|
|
|
|
Reconnect runtime
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
<% else %>
|
|
|
|
<div class="text-red-600">
|
|
|
|
<span class="font-semibold">Note:</span>
|
|
|
|
This operation requires restarting the runtime, but we cannot
|
|
|
|
do it automatically for the current runtime
|
|
|
|
</div>
|
|
|
|
<% end %>
|
2021-11-09 03:45:30 +08:00
|
|
|
</div>
|
|
|
|
"""
|
|
|
|
end
|
|
|
|
|
2021-11-26 01:43:42 +08:00
|
|
|
defp render_output({:error, formatted, _type}, %{}) do
|
2022-01-26 04:55:24 +08:00
|
|
|
render_error(formatted)
|
2021-11-09 03:45:30 +08:00
|
|
|
end
|
|
|
|
|
2022-01-17 20:24:59 +08:00
|
|
|
# TODO: remove on Livebook v0.7
|
|
|
|
defp render_output(output, %{})
|
|
|
|
when elem(output, 0) in [
|
|
|
|
:vega_lite_static,
|
|
|
|
:vega_lite_dynamic,
|
|
|
|
:table_dynamic,
|
|
|
|
:frame_dynamic
|
|
|
|
] do
|
2022-01-26 04:55:24 +08:00
|
|
|
render_error_message("""
|
2022-01-17 20:24:59 +08:00
|
|
|
Legacy output format: #{inspect(output)}. Please update Kino to
|
|
|
|
the latest version.
|
|
|
|
""")
|
|
|
|
end
|
|
|
|
|
2021-11-26 01:43:42 +08:00
|
|
|
defp render_output(output, %{}) do
|
2022-01-26 04:55:24 +08:00
|
|
|
render_error_message("""
|
2021-11-09 03:45:30 +08:00
|
|
|
Unknown output format: #{inspect(output)}. If you're using Kino,
|
|
|
|
you may want to update Kino and Livebook to the latest version.
|
|
|
|
""")
|
|
|
|
end
|
|
|
|
|
2022-01-26 04:55:24 +08:00
|
|
|
defp render_error(message) do
|
|
|
|
assigns = %{message: message}
|
|
|
|
|
|
|
|
~H"""
|
2022-02-18 06:37:14 +08:00
|
|
|
<div class="whitespace-pre-wrap font-editor text-gray-500" role="complementary" aria-label="error"><%= ansi_string_to_html(@message) %></div>
|
2022-01-26 04:55:24 +08:00
|
|
|
"""
|
|
|
|
end
|
|
|
|
|
|
|
|
defp render_error_message(message) do
|
2021-11-09 03:45:30 +08:00
|
|
|
assigns = %{message: message}
|
|
|
|
|
|
|
|
~H"""
|
2022-02-18 06:37:14 +08:00
|
|
|
<div class="whitespace-pre-wrap font-editor text-red-600" role="complementary" aria-label="error message"><%= @message %></div>
|
2021-11-09 03:45:30 +08:00
|
|
|
"""
|
|
|
|
end
|
|
|
|
end
|