Skip to content

Commit

Permalink
fix: node insert
Browse files Browse the repository at this point in the history
  • Loading branch information
sorax committed May 21, 2024
1 parent ab9e771 commit 72f7eed
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 57 deletions.
6 changes: 2 additions & 4 deletions assets/js/hooks/events/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,6 @@ export function handleDelete({ node }: { node: Node }) {
}

export function handleClean({ node }: { node: Node }) {
const container: HTMLOListElement = this.el;

node.dirty = false;
updateItem(node, container);
const item = getItemById(node.uuid)
item && setItemDirty(item, false);
}
11 changes: 6 additions & 5 deletions assets/js/hooks/events/listener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
deleteItem,
getItemByNode,
focusItem,
setItemDirty,
} from "../item";
import { getNodeByEvent, getNodeByItem } from "../node";

Expand All @@ -22,7 +23,9 @@ export function focusout(event: FocusEvent) {

export function input(event: Event) {
const node = getNodeByEvent(event);
node.dirty = true;
const item = getItemByNode(node);
item && setItemDirty(item, true);

this.pushEvent("update_node", node);
}

Expand Down Expand Up @@ -99,13 +102,12 @@ export function keydown(event: KeyboardEvent) {
if (!prevItem || !prevNode) return;

prevNode.content += node.content || "";
prevNode.dirty = true;
updateItem(prevNode, container);
focusItem(prevItem);
prevNode.dirty = true;
this.pushEvent("update_node", prevNode);

deleteItem(node);
node.dirty = true;
this.pushEvent("delete_node", node);
break;

Expand All @@ -116,13 +118,12 @@ export function keydown(event: KeyboardEvent) {
if (!nextItem || !nextNode) return;

node.content += nextNode.content || "";
node.dirty = true;
updateItem(node, container);
focusItem(item);
node.dirty = true;
this.pushEvent("update_node", node);

deleteItem(nextNode);
nextNode.dirty = true;
this.pushEvent("delete_node", nextNode);
break;

Expand Down
14 changes: 5 additions & 9 deletions assets/js/hooks/item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ export function createItem({ uuid, content, parent_id, prev_id, dirty }: Node) {

const item = document.createElement("li");
item.id = "outline-node-" + uuid;
item.className = dirty ? "my-1 ml-4 bg-red-100" : "my-1 ml-4";
item.className = "my-1 ml-4 data-[dirty=true]:bg-red-100";

item.setAttribute("data-parent", parent_id || "");
item.setAttribute("data-prev", prev_id || "");
item.setAttribute("data-dirty", dirty ? "true" : "false");

setItemDirty(item, dirty)

item.appendChild(input);
item.appendChild(ol);
Expand All @@ -27,17 +28,15 @@ export function updateItem(
container: HTMLOListElement
) {
const item = getItemById(uuid);
console.log({ item, uuid, content, parent_id, prev_id, dirty });
if (!item) return;

const input = item.firstChild!;
input.textContent = content || "";

item.className = dirty ? "my-1 ml-4 bg-red-100" : "my-1 ml-4";

item.setAttribute("data-parent", parent_id || "");
item.setAttribute("data-prev", prev_id || "");
item.setAttribute("data-dirty", dirty ? "true" : "false");

setItemDirty(item, dirty)

const prevItem = getItemById(prev_id);
const parentItem = getItemById(parent_id);
Expand All @@ -46,8 +45,6 @@ export function updateItem(
prevItem.after(item);
} else if (parentItem) {
parentItem.querySelector("ol")?.append(item);
} else {
container.append(item);
}
}

Expand Down Expand Up @@ -99,6 +96,5 @@ export function focusItem(item: HTMLLIElement, toEnd: boolean = true) {
// }

export function setItemDirty(item: HTMLLIElement, dirty: boolean) {
item.className = dirty ? "my-1 ml-4 bg-red-100" : "my-1 ml-4";
item.setAttribute("data-dirty", dirty ? "true" : "false");
}
2 changes: 1 addition & 1 deletion assets/js/hooks/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ export interface Node {
creator_id?: number;
parent_id?: UUID;
prev_id?: UUID;
dirty?: boolean;
dirty: boolean;
}
4 changes: 2 additions & 2 deletions lib/radiator/outline.ex
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ defmodule Radiator.Outline do
# if no previous node is given, the new node will be inserted as the first child of the parent node
def insert_node(attrs) do
Repo.transaction(fn ->
prev_node_id = attrs["prev_node"]
parent_node_id = attrs["parent_node"]
prev_node_id = attrs["prev_id"]
parent_node_id = attrs["parent_id"]
episode_id = attrs["episode_id"]
# find Node which has been previously connected to prev_node
node_to_move =
Expand Down
15 changes: 8 additions & 7 deletions lib/radiator_web/live/episode_live/index.ex
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ defmodule RadiatorWeb.EpisodeLive.Index do
|> reply(:noreply)
end

@impl true
def handle_event("validate", %{"episode" => params}, socket) do
changeset = socket.assigns.episode |> Episode.changeset(params) |> Map.put(:action, :validate)

Expand All @@ -100,7 +99,6 @@ defmodule RadiatorWeb.EpisodeLive.Index do
|> reply(:noreply)
end

@impl true
def handle_event("save", %{"episode" => params}, socket) do
show_id = socket.assigns.show.id

Expand All @@ -126,12 +124,15 @@ defmodule RadiatorWeb.EpisodeLive.Index do
end

@impl true
def handle_info(
%{node: node, event_id: <<_::binary-size(36)>> <> ":" <> id},
%{id: id} = socket
) do
def handle_info(%{event_id: <<_::binary-size(36)>> <> ":" <> id} = payload, %{id: id} = socket) do
id =
case payload do
%{node: %{uuid: id}} -> id
%{node_id: id} -> id
end

socket
|> push_event("clean", %{node: node})
|> push_event("clean", %{node: %{uuid: id}})
|> reply(:noreply)
end

Expand Down
52 changes: 35 additions & 17 deletions test/radiator/outline_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,24 @@ defmodule Radiator.OutlineTest do
describe "insert_node/1" do
setup :complex_node_fixture

test "node can be inserted after another node", %{node_3: node_3, node_4: node_4} do
node_attrs = %{
"content" => "node 3.1",
"episode_id" => node_3.episode_id,
"parent_id" => node_3.parent_id,
"prev_id" => node_3.uuid
}

assert {:ok, %Node{uuid: node3_1_uuid} = node} = Outline.insert_node(node_attrs)

assert node.parent_id == node_3.parent_id
assert node.prev_id == node_3.uuid

node4 = Repo.reload!(node_4)

assert node4.prev_id == node3_1_uuid
end

test "creates a new node in the tree", %{
node_3: node_3,
nested_node_1: nested_node_1
Expand All @@ -68,8 +86,8 @@ defmodule Radiator.OutlineTest do
node_attrs = %{
"content" => "new node",
"episode_id" => node_3.episode_id,
"parent_node" => node_3.uuid,
"prev_node" => nested_node_1.uuid
"parent_id" => node_3.uuid,
"prev_id" => nested_node_1.uuid
}

Outline.insert_node(node_attrs)
Expand All @@ -84,8 +102,8 @@ defmodule Radiator.OutlineTest do
node_attrs = %{
"content" => "new node",
"episode_id" => node_3.episode_id,
"parent_node" => node_3.uuid,
"prev_node" => nested_node_1.uuid
"parent_id" => node_3.uuid,
"prev_id" => nested_node_1.uuid
}

{:ok, new_node} = Outline.insert_node(node_attrs)
Expand All @@ -99,8 +117,8 @@ defmodule Radiator.OutlineTest do
node_attrs = %{
"content" => "new node",
"episode_id" => node_3.episode_id,
"parent_node" => node_3.uuid,
"prev_node" => nested_node_1.uuid
"parent_id" => node_3.uuid,
"prev_id" => nested_node_1.uuid
}

{:ok, new_node} = Outline.insert_node(node_attrs)
Expand All @@ -115,8 +133,8 @@ defmodule Radiator.OutlineTest do
node_attrs = %{
"content" => "new node",
"episode_id" => node_3.episode_id,
"parent_node" => node_3.uuid,
"prev_node" => nested_node_1.uuid
"parent_id" => node_3.uuid,
"prev_id" => nested_node_1.uuid
}

{:ok, new_node} = Outline.insert_node(node_attrs)
Expand All @@ -134,8 +152,8 @@ defmodule Radiator.OutlineTest do
node_attrs = %{
"content" => "new node",
"episode_id" => node_3.episode_id,
"parent_node" => node_3.uuid,
"prev_node" => nested_node_2.uuid
"parent_id" => node_3.uuid,
"prev_id" => nested_node_2.uuid
}

{:ok, new_node} = Outline.insert_node(node_attrs)
Expand All @@ -153,7 +171,7 @@ defmodule Radiator.OutlineTest do
node_attrs = %{
"content" => "new node",
"episode_id" => node_3.episode_id,
"parent_node" => node_3.uuid
"parent_id" => node_3.uuid
}

{:ok, new_node} = Outline.insert_node(node_attrs)
Expand Down Expand Up @@ -184,8 +202,8 @@ defmodule Radiator.OutlineTest do
node_attrs = %{
"content" => "new node",
"episode_id" => parent_node.episode_id,
"parent_node" => parent_node.uuid,
"prev_node" => nested_node_1.uuid
"parent_id" => parent_node.uuid,
"prev_id" => nested_node_1.uuid
}

{:error, "Insert node failed. Parent and prev node are not consistent."} =
Expand All @@ -201,8 +219,8 @@ defmodule Radiator.OutlineTest do
node_attrs = %{
"content" => "new node",
"episode_id" => parent_node.episode_id,
"parent_node" => parent_node.uuid,
"prev_node" => bad_parent_node.uuid
"parent_id" => parent_node.uuid,
"prev_id" => bad_parent_node.uuid
}

{:error, _error_message} =
Expand All @@ -218,8 +236,8 @@ defmodule Radiator.OutlineTest do
node_attrs = %{
"content" => "new node",
"episode_id" => parent_node.episode_id,
"parent_node" => parent_node.uuid,
"prev_node" => nested_node_1.uuid
"parent_id" => parent_node.uuid,
"prev_id" => nested_node_1.uuid
}

{:error, _error_message} = Outline.insert_node(node_attrs)
Expand Down
32 changes: 20 additions & 12 deletions test/radiator_web/live/episode_live_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ defmodule RadiatorWeb.EpisodeLiveTest do
node_2 = node_fixture(%{episode_id: episode.id, prev_id: node_1.uuid})
_node_21 = node_fixture(%{episode_id: episode.id, parent_id: node_2.uuid})

%{conn: log_in_user(conn, user), show: show, episode: episode}
%{conn: log_in_user(conn, user), show: show, episode: episode, nodes: [node_1, node_2]}
end

test "lists all nodes", %{conn: conn, show: show} do
Expand All @@ -66,20 +66,28 @@ defmodule RadiatorWeb.EpisodeLiveTest do
assert_push_event(live, "list", %{nodes: ^nodes})
end

# test "insert a new node", %{conn: conn, show: show} do
# {:ok, live, _html} = live(conn, ~p"/admin/podcast/#{show.id}")
# {:ok, other_live, _html} = live(conn, ~p"/admin/podcast/#{show.id}")
test "insert a new node", %{conn: conn, show: show, nodes: [node_1 | _]} do
{:ok, live, _html} = live(conn, ~p"/admin/podcast/#{show.id}")
{:ok, other_live, _html} = live(conn, ~p"/admin/podcast/#{show.id}")

uuid = Ecto.UUID.generate()

# uuid = Ecto.UUID.generate()
# event_id = Ecto.UUID.generate()
params = %{
"uuid" => uuid,
"content" => "new node temp content",
# "parent_id" => nil,
"prev_id" => node_1.uuid
}

# params = %{"uuid" => uuid, "event_id" => event_id, "content" => "new node temp content"}
# assert live |> render_hook(:create_node, params)
assert live |> render_hook(:create_node, params)

# node = NodeRepository.get_node!(uuid)
# assert_push_event(live, "insert", %{node: ^node, event_id: ^event_id})
# assert_push_event(other_live, "insert", %{node: ^node, event_id: ^event_id})
# end
node = NodeRepository.get_node!(uuid)
assert node.parent_id == nil
assert node.prev_id == node_1.uuid

assert_push_event(live, "clean", %{node: %{uuid: ^uuid}})
assert_push_event(other_live, "insert", %{node: ^node})
end

# test "receive node inserted event after inserting a node", %{conn: conn, show: show} do
# {:ok, live, _html} = live(conn, ~p"/admin/podcast/#{show.id}")
Expand Down

0 comments on commit 72f7eed

Please sign in to comment.