Skip to content

Commit

Permalink
implement Outline.merge_next_node
Browse files Browse the repository at this point in the history
  • Loading branch information
electronicbites committed Dec 29, 2024
1 parent 614029d commit 0d733ce
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 5 deletions.
51 changes: 51 additions & 0 deletions lib/radiator/outline.ex
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ defmodule Radiator.Outline do
@moduledoc """
The Outline context.
"""
import Ecto.Query

alias Radiator.Outline.Node
alias Radiator.Outline.NodeRepoResult
Expand Down Expand Up @@ -346,6 +347,56 @@ defmodule Radiator.Outline do
{first, last}
end

def merge_prev_node(_node_id) do
nil
end

def merge_next_node(%Node{} = node) do
merge_next_node(node, NodeRepository.get_next_node(node))
end

def merge_next_node(node_id), do: merge_next_node(NodeRepository.get_node!(node_id))

def merge_next_node(%Node{} = _node, nil), do: {:error, :no_next_node}

def merge_next_node(
%Node{uuid: node_id} = node,
%Node{uuid: next_node_id, content: content_of_next_node} = next_node
) do
Ecto.Multi.new()
|> Ecto.Multi.update_all(
:update_childrens,
fn _ ->
from(n in Node, where: n.parent_id == ^next_node_id, update: [set: [parent_id: ^node_id]])
end,
[]
)
|> Ecto.Multi.update(:update_content, fn _changes ->
Node.update_content_changeset(node, %{content: node.content <> content_of_next_node})
end)
|> Ecto.Multi.run(:delete_next_node, fn _, _ ->
%NodeRepoResult{node: deleted_node, next: updated_next_node} = remove_node(next_node)
{:ok, %{deleted_node: deleted_node, updated_next_node: updated_next_node}}
end)
|> Repo.transaction()
|> case do
{:ok, result} ->
node = result.update_content

{:ok,
%NodeRepoResult{
node: result.update_content,
old_next: result.delete_next_node.deleted_node,
next: result.delete_next_node.updated_next_node,
children: NodeRepository.get_all_siblings(node),
outline_node_container_id: node.outline_node_container_id
}}

{:error, _tag, error, _others} ->
{:error, error}
end
end

@doc """
Removes a node from the tree and deletes it from the repository.
Recursivly deletes all children if there are some.
Expand Down
7 changes: 2 additions & 5 deletions lib/radiator/outline/command_processor.ex
Original file line number Diff line number Diff line change
Expand Up @@ -167,12 +167,9 @@ defmodule Radiator.Outline.CommandProcessor do
# delete current node
end

defp process_command(%MergeNextNodeCommand{node_id: _node_id} = _command) do
# node_id has a next node?
defp process_command(%MergeNextNodeCommand{node_id: node_id} = _command) do
Outline.merge_next_node(node_id)

# get content from next node -> append content to current node

# delete next node
end

defp handle_insert_node_result(
Expand Down
1 change: 1 addition & 0 deletions lib/radiator/outline/node_repository.ex
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ defmodule Radiator.Outline.NodeRepository do
end

@doc """
TODO wrong name: sibling is "geschwister" in german
Returns all direct child nodes of a given node.
## Examples
iex> get_all_siblings(%Node{})
Expand Down
40 changes: 40 additions & 0 deletions test/radiator/outline_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -832,6 +832,46 @@ defmodule Radiator.OutlineTest do
end
end

describe "merge_next_node/1" do
setup :complex_node_fixture

test "merges two nodes into one", %{
node_2: node_2,
node_3: node_3,
nested_node_1: nested_node_1,
nested_node_2: nested_node_2,
node_4: node_4
} do
{:ok, result} = Outline.merge_next_node(node_2)

node_2 = Repo.reload!(node_2)
node_4 = Repo.reload!(node_4)
nested_node_1 = Repo.reload!(nested_node_1)
nested_node_2 = Repo.reload!(nested_node_2)
assert is_nil(NodeRepository.get_node(node_3.uuid))
assert nested_node_2.parent_id == node_2.uuid
assert nested_node_1.parent_id == node_2.uuid
assert node_4.prev_id == node_2.uuid
assert node_2.content == "node_2node_3"

assert result.node.uuid == node_2.uuid
assert result.old_next.uuid == node_3.uuid
assert result.next.uuid == node_4.uuid
assert Enum.count(result.children) == 2
end

test "ignores command when there is no next node", %{
node_6: node_6
} do
old_content = node_6.content
{:error, :no_next_node} = Outline.merge_next_node(node_6)
assert is_nil(NodeRepository.get_next_node(node_6))
{:error, :no_next_node} = Outline.merge_next_node(node_6)
node_6 = Repo.reload!(node_6)
assert old_content == node_6.content
end
end

describe "indent_node/1 - simple context" do
setup :simple_node_fixture

Expand Down

0 comments on commit 0d733ce

Please sign in to comment.