Don't render cell initial data and make a request instead

This commit is contained in:
Jonatan Kłosko 2021-01-29 21:36:12 +01:00
parent e0d2adfa64
commit cc752542de
3 changed files with 61 additions and 45 deletions

View file

@ -18,44 +18,42 @@ import Markdown from "./markdown";
* * `data-type` - editor type (i.e. language), either "markdown" or "elixir" is expected
* * `data-focused` - whether the cell is currently focused
* * `data-expanded` - whether the cell is currently expanded (relevant for markdown cells)
*
* Additionally the root element should have a `div[data-init]` child (rendered once)
* holding the initial data rendered only once:
*
* * `data-source` - the initial cell source
* * `data-revision` - the initial cell revision corresponding to the source
*/
const Cell = {
mounted() {
this.props = getProps(this);
const editorContainer = this.el.querySelector("[data-editor-container]");
// Remove the content placeholder.
editorContainer.firstElementChild.remove();
// Create an empty container for the editor to be mounted in.
const editorElement = document.createElement("div");
editorContainer.appendChild(editorElement);
// Setup the editor instance.
this.liveEditor = new LiveEditor(
this,
editorElement,
this.props.cellId,
this.props.type,
this.props.init.source,
this.props.init.revision
);
this.pushEvent("cell_init", { cell_id: this.props.cellId }, (payload) => {
const { source, revision } = payload;
// Setup markdown rendering.
if (this.props.type === "markdown") {
const markdownContainer = this.el.querySelector(
"[data-markdown-container]"
const editorContainer = this.el.querySelector("[data-editor-container]");
// Remove the content placeholder.
editorContainer.firstElementChild.remove();
// Create an empty container for the editor to be mounted in.
const editorElement = document.createElement("div");
editorContainer.appendChild(editorElement);
// Setup the editor instance.
this.liveEditor = new LiveEditor(
this,
editorElement,
this.props.cellId,
this.props.type,
source,
revision
);
const markdown = new Markdown(markdownContainer, this.props.init.source);
this.liveEditor.onChange((newSource) => {
markdown.setContent(newSource);
});
}
// Setup markdown rendering.
if (this.props.type === "markdown") {
const markdownContainer = this.el.querySelector(
"[data-markdown-container]"
);
const markdown = new Markdown(markdownContainer, source);
this.liveEditor.onChange((newSource) => {
markdown.setContent(newSource);
});
}
});
},
updated() {
@ -73,17 +71,11 @@ const Cell = {
};
function getProps(hook) {
const initElement = hook.el.querySelector("[data-init]");
return {
cellId: getAttributeOrThrow(hook.el, "data-cell-id"),
type: getAttributeOrThrow(hook.el, "data-type"),
isFocused: getAttributeOrThrow(hook.el, "data-focused", parseBoolean),
isExpanded: getAttributeOrThrow(hook.el, "data-expanded", parseBoolean),
init: {
source: getAttributeOrThrow(initElement, "data-source"),
revision: getAttributeOrThrow(initElement, "data-revision", parseInteger),
},
};
}

View file

@ -10,11 +10,6 @@ defmodule LiveBookWeb.Cell do
data-focused="<%= @focused %>"
data-expanded="<%= @expanded %>"
class="flex flex-col relative mr-10 border-l-4 pl-4 -ml-4 border-blue-100 border-opacity-0 hover:border-opacity-100 <%= if @focused, do: "border-blue-300 border-opacity-100"%>">
<div id="init-container-<%= @cell.id %>" phx-update="ignore">
<div data-init data-source="<%= @cell.source %>" data-revision="<%= @cell_info.revision %>">
</div>
</div>
<%= render_cell_content(assigns) %>
</div>
"""
@ -33,7 +28,7 @@ defmodule LiveBookWeb.Cell do
</div>
<div class="markdown" data-markdown-container id="markdown-container-<%= @cell.id %>" phx-update="ignore">
<%= render_markdown_content_placeholder() %>
<%= render_markdown_content_placeholder(@cell.source) %>
</div>
"""
end
@ -59,7 +54,7 @@ defmodule LiveBookWeb.Cell do
data-editor-container
id="editor-container-<%= cell.id %>"
phx-update="ignore">
<%= render_editor_content_placeholder() %>
<%= render_editor_content_placeholder(cell.source) %>
</div>
"""
end
@ -68,7 +63,13 @@ defmodule LiveBookWeb.Cell do
# There may be a tiny delay before the markdown is rendered
# or and editors are mounted, so show neat placeholders immediately.
defp render_markdown_content_placeholder() do
defp render_markdown_content_placeholder("" = _content) do
~E"""
<div class="h-4"></div>
"""
end
defp render_markdown_content_placeholder(_content) do
~E"""
<div class="max-w-2xl w-full animate-pulse">
<div class="flex-1 space-y-4">
@ -80,7 +81,13 @@ defmodule LiveBookWeb.Cell do
"""
end
defp render_editor_content_placeholder() do
defp render_editor_content_placeholder("" = _content) do
~E"""
<div class="h-4"></div>
"""
end
defp render_editor_content_placeholder(_content) do
~E"""
<div class="px-8 max-w-2xl w-full animate-pulse">
<div class="flex-1 space-y-4 py-1">

View file

@ -88,6 +88,23 @@ defmodule LiveBookWeb.SessionLive do
end
@impl true
def handle_event("cell_init", %{"cell_id" => cell_id}, socket) do
data = socket.assigns.data
case Notebook.fetch_cell_and_section(data.notebook, cell_id) do
{:ok, cell, _section} ->
payload = %{
source: cell.source,
revision: data.cell_infos[cell.id].revision
}
{:reply, payload, socket}
:error ->
{:noreply, socket}
end
end
def handle_event("add_section", _params, socket) do
end_index = length(socket.assigns.data.notebook.sections)
Session.insert_section(socket.assigns.session_id, end_index)