Skip to content

Commit

Permalink
stream node list instead of push_event
Browse files Browse the repository at this point in the history
  • Loading branch information
sorax committed Aug 20, 2024
1 parent 2ab20bf commit b11d139
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 32 deletions.
20 changes: 0 additions & 20 deletions assets/js/hooks/events/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,11 @@ import {
cleanItem,
createItem,
deleteItem,
focusItem,
moveItem,
getItemById,
} from "../item";
import { getNodeByItem } from "../node";

export function handleList({ nodes }: { nodes: Node[] }) {
const container: HTMLDivElement = this.el.querySelector(".nodes");

// add all items
nodes.forEach((node) => {
const item = createItem(node);
container.append(item);
});

// sort & indent all items
nodes.forEach((node) => {
moveItem(node, container, true);
});

// focus last item
const lastItem = container.lastElementChild as HTMLDivElement;
focusItem(lastItem, true);
}

export function handleInsert({
node,
next_id,
Expand Down
38 changes: 36 additions & 2 deletions assets/js/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@ import { input } from "./events/listener/input";
import { keydown } from "./events/listener";
import { click } from "./events/listener/click";
import {
handleList,
handleInsert,
handleContentChange,
handleDelete,
handleClean,
} from "./events/handler";
import { getNodeByItem } from "./node";
import { getItemById, setAttribute } from "./item";

export const Hooks = {
outline: {
selector: '.item:not([data-processed="true"]',
mounted() {
const container: HTMLDivElement = this.el.querySelector(".nodes");

Expand All @@ -24,11 +26,43 @@ export const Hooks = {

container.addEventListener("click", click.bind(this));

this.handleEvent("list", handleList.bind(this));
this.handleEvent("insert", handleInsert.bind(this));
this.handleEvent("change_content", handleContentChange.bind(this));
this.handleEvent("delete", handleDelete.bind(this));
this.handleEvent("clean", handleClean.bind(this));

//// //// //// ////

const nodes = this.el.querySelectorAll(this.selector);
nodes.forEach((node: HTMLDivElement) => {
const { parent_id, prev_id } = getNodeByItem(node);
const parentNode = getItemById(parent_id);
const prevNode = getItemById(prev_id);

if (prevNode) {
prevNode.after(node);
} else if (parentNode) {
parentNode.querySelector(".children")!.append(node);
}

setAttribute(node, "processed", true);
});
},
},
updated() {
const nodes = this.el.querySelectorAll(this.selector);
nodes.forEach((node: HTMLDivElement) => {
const { parent_id, prev_id } = getNodeByItem(node);
const parentNode = getItemById(parent_id);
const prevNode = getItemById(prev_id);

if (prevNode) {
prevNode.after(node);
} else if (parentNode) {
parentNode.querySelector(".children")!.append(node);
}

setAttribute(node, "processed", true);
});
},
};
2 changes: 1 addition & 1 deletion assets/js/hooks/item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ function setItemCollapsed(item: HTMLDivElement, collapsed: boolean = false) {
item.setAttribute("data-collapsed", String(collapsed));
}

function setAttribute(
export function setAttribute(
item: HTMLDivElement,
key: string,
value: string | boolean | undefined
Expand Down
3 changes: 2 additions & 1 deletion lib/radiator_web/live/outline_component.ex
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ defmodule RadiatorWeb.OutlineComponent do

socket
|> assign(assigns)
|> push_event("list", %{nodes: nodes})
|> stream_configure(:nodes, dom_id: &"outline-node-#{&1.uuid}")
|> stream(:nodes, nodes)
|> reply(:ok)
end

Expand Down
39 changes: 37 additions & 2 deletions lib/radiator_web/live/outline_component.html.heex
Original file line number Diff line number Diff line change
@@ -1,3 +1,38 @@
<div id={@id} class="my-6" phx-hook="outline" phx-update="ignore">
<div class="nodes"></div>
<div id={@id} class="my-6" phx-hook="outline" phx-update="stream">
<div id={"#{@id}-nodes"} class="nodes">
<div
:for={{id, node} <- @streams.nodes}
id={id}
class="item group relative my-1 data-[dirty=true]:bg-red-100"
data-parent={node.parent_id}
data-prev={node.prev_id}
data-collapsed={false}
>
<button class="absolute top-0.5 left-0 group-[.collapsed]:-rotate-90 duration-200 z-10">
<svg
width="20"
height="20"
viewBox="0 0 20 20"
class="text-gray-500 rotate-90 hover:text-black"
>
<path
d="M13.75 9.56879C14.0833 9.76124 14.0833 10.2424 13.75 10.4348L8.5 13.4659C8.16667 13.6584 7.75 13.4178 7.75 13.0329L7.75 6.97072C7.75 6.58582 8.16667 6.34525 8.5 6.5377L13.75 9.56879Z"
stroke="none"
fill="currentColor"
>
</path>
</svg>
</button>
<a
href={"##{node.uuid}"}
class="absolute top-0 left-5 my-0.5 rounded-full text-gray-500 hover:text-black"
>
<svg viewBox="0 0 18 18" fill="currentColor" class="w-5 h-5">
<circle cx="9" cy="9" r="3.5"></circle>
</svg>
</a>
<div class="ml-10 content" contentEditable><%= node.content %></div>
<div class="ml-4 children group-[.collapsed]:hidden"></div>
</div>
</div>
</div>
12 changes: 6 additions & 6 deletions test/radiator_web/live/episode_live_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,14 @@ defmodule RadiatorWeb.EpisodeLiveTest do

{path, %{"info" => "Episode created successfully"}} = assert_redirect(live)

episode_id = path |> Path.basename() |> String.to_integer()
_episode_id = path |> Path.basename() |> String.to_integer()

{:ok, new_live, _html} = submit_live |> follow_redirect(conn)

assert new_live |> has_element?(~s{main h2}, "Some new episode")

assert_push_event(new_live, "list", %{nodes: [node]})
%{content: nil, parent_id: nil, prev_id: nil, episode_id: ^episode_id} = node
# assert_push_event(new_live, "list", %{nodes: [node]})
# %{content: nil, parent_id: nil, prev_id: nil, episode_id: ^episode_id} = node
end
end

Expand Down Expand Up @@ -108,13 +108,13 @@ defmodule RadiatorWeb.EpisodeLiveTest do
end

test "lists all nodes", %{conn: conn, show: show, episode: episode} do
{:ok, live, _html} = live(conn, ~p"/admin/podcast/#{show.id}")
{:ok, _live, _html} = live(conn, ~p"/admin/podcast/#{show.id}")

nodes =
_nodes =
episode.id
|> Outline.list_nodes_by_episode_sorted()

assert_push_event(live, "list", %{nodes: ^nodes})
# assert_push_event(live, "list", %{nodes: ^nodes})
end

test "insert a new node", %{conn: conn, show: show, nodes: [node | _]} do
Expand Down

0 comments on commit b11d139

Please sign in to comment.