refactor(ui): replace manual template inheritance tree with TreeView component

This commit is contained in:
Joseph Doherty
2026-03-23 06:04:48 -04:00
parent 2b5dabb336
commit a0a6bb4986

View File

@@ -33,16 +33,14 @@
<button class="btn btn-primary btn-sm" @onclick='() => NavigationManager.NavigateTo("/design/templates/create")'>New Template</button>
</div>
@* Inheritance tree visualization *@
<div class="card">
<div class="card-body p-2">
@foreach (var node in BuildTemplateTree())
{
<div class="d-flex align-items-center py-1 border-bottom"
style="padding-left: @(node.Depth * 24 + 8)px; cursor: pointer;"
@onclick="() => SelectTemplate(node.Template.Id)">
<span class="me-2 text-muted small">@(node.HasChildren ? "[+]" : " -")</span>
<span class="flex-grow-1">
<TreeView TItem="TmplTreeNode" Items="_templateTreeRoots"
ChildrenSelector="n => n.Children"
HasChildrenSelector="n => n.Children.Count > 0"
KeySelector="n => (object)n.Template.Id"
StorageKey="templates-tree"
Selectable="true"
SelectedKeyChanged="key => { if (key is int id) _ = SelectTemplate(id); }">
<NodeContent Context="node">
<strong>@node.Template.Name</strong>
@if (node.Template.ParentTemplateId.HasValue)
{
@@ -52,20 +50,27 @@
{
<span class="text-muted small ms-2">@node.Template.Description</span>
}
</span>
<span class="badge bg-light text-dark me-2">
<span class="badge bg-light text-dark ms-2">
@node.Template.Attributes.Count attr, @node.Template.Alarms.Count alm, @node.Template.Scripts.Count scr
</span>
@if (node.Template.Compositions.Count > 0)
{
<span class="badge bg-info text-dark me-2">@node.Template.Compositions.Count comp</span>
<span class="badge bg-info text-dark ms-1">@node.Template.Compositions.Count comp</span>
}
<button class="btn btn-outline-danger btn-sm py-0 px-1"
@onclick="() => DeleteTemplate(node.Template)" @onclick:stopPropagation="true">Delete</button>
</div>
}
</div>
</div>
</NodeContent>
<ContextMenu Context="node">
<button class="dropdown-item" @onclick="() => SelectTemplate(node.Template.Id)">
Edit
</button>
<div class="dropdown-divider"></div>
<button class="dropdown-item text-danger" @onclick="() => DeleteTemplate(node.Template)">
Delete
</button>
</ContextMenu>
<EmptyContent>
<span class="text-muted fst-italic">No templates. Create one to get started.</span>
</EmptyContent>
</TreeView>
}
else
{
@@ -275,6 +280,7 @@
try
{
_templates = (await TemplateEngineRepository.GetAllTemplatesAsync()).ToList();
BuildTemplateTree();
}
catch (Exception ex)
{
@@ -283,24 +289,22 @@
_loading = false;
}
private record TemplateTreeNode(Template Template, int Depth, bool HasChildren);
private record TmplTreeNode(Template Template, List<TmplTreeNode> Children);
private List<TemplateTreeNode> BuildTemplateTree()
private List<TmplTreeNode> _templateTreeRoots = new();
private void BuildTemplateTree()
{
var result = new List<TemplateTreeNode>();
AddTemplateChildren(null, 0, result);
return result;
_templateTreeRoots = BuildTmplChildren(null);
}
private void AddTemplateChildren(int? parentId, int depth, List<TemplateTreeNode> result)
private List<TmplTreeNode> BuildTmplChildren(int? parentId)
{
var children = _templates.Where(t => t.ParentTemplateId == parentId).OrderBy(t => t.Name);
foreach (var child in children)
{
var hasChildren = _templates.Any(t => t.ParentTemplateId == child.Id);
result.Add(new TemplateTreeNode(child, depth, hasChildren));
AddTemplateChildren(child.Id, depth + 1, result);
}
return _templates
.Where(t => t.ParentTemplateId == parentId)
.OrderBy(t => t.Name)
.Select(t => new TmplTreeNode(t, BuildTmplChildren(t.Id)))
.ToList();
}
private async Task SelectTemplate(int templateId)