feat: collapsable hierarchical view

This commit is contained in:
Schuwi
2025-09-19 21:54:34 +02:00
parent 8fe199f50c
commit 288d84614a
3 changed files with 353 additions and 106 deletions

View File

@@ -275,4 +275,60 @@ defmodule ComponentsElixir.Inventory.Hierarchical do
[child | sort_children_recursively(entities, child.id, parent_id_accessor_fn)]
end)
end
@doc """
Calculates component counts for an entity and all its descendants.
Returns a tuple of {self_count, children_count, total_count}.
## Parameters
- entity_id: The ID of the entity to count for
- all_entities: List of all entities in the hierarchy
- parent_id_accessor_fn: Function to get parent_id from an entity
- count_fn: Function that takes an entity_id and returns the direct count for that entity
## Examples
iex> count_fn = fn id -> MyRepo.count_components_for(id) end
iex> Hierarchical.count_with_descendants(1, entities, &(&1.parent_id), count_fn)
{3, 7, 10} # 3 in self, 7 in children, 10 total
"""
def count_with_descendants(entity_id, all_entities, parent_id_accessor_fn, count_fn) do
# Get direct count for this entity
self_count = count_fn.(entity_id)
# Get all descendant entity IDs (excluding self)
all_descendant_ids = descendant_ids(all_entities, entity_id, parent_id_accessor_fn)
descendant_ids_only = List.delete(all_descendant_ids, entity_id)
# Sum counts for all descendants
children_count = Enum.reduce(descendant_ids_only, 0, fn id, acc ->
acc + count_fn.(id)
end)
{self_count, children_count, self_count + children_count}
end
@doc """
Formats component count display based on expansion state.
When collapsed: Shows total count only: "10 components"
When expanded: Shows breakdown: "10 components (3 self, 7 children)"
## Parameters
- self_count: Number of components directly in this entity
- children_count: Number of components in all descendant entities
- is_expanded: Whether the entity is currently expanded
- singular_noun: What to call a single item (default: "component")
- plural_noun: What to call multiple items (default: "components")
"""
def format_count_display(self_count, children_count, is_expanded, singular_noun \\ "component", plural_noun \\ "components") do
total_count = self_count + children_count
count_noun = if total_count == 1, do: singular_noun, else: plural_noun
if is_expanded and children_count > 0 do
"#{total_count} #{count_noun} (#{self_count} self, #{children_count} children)"
else
"#{total_count} #{count_noun}"
end
end
end