Files
Tasks.Module/Components/Sidebar/FolderTreeItem.razor
T
2026-08-07 02:17:32 +03:00

154 lines
4.7 KiB
Plaintext

@using MudBlazor
@using Microsoft.AspNetCore.Components.Web
@using Tasks.Module.Models
<div class="folder-item @(Item.Type == TreeItemType.Folder ? "drop-zone" : "") @(Item.IsDragOver ? "drop-zone-active" : "") @(Item.IsDragSource ? "drag-source" : "")"
draggable="true"
@onclick="@(() => OnClick(Item))"
@oncontextmenu:preventDefault="true"
@oncontextmenu="@OnContextMenuHandler"
@ondragstart="@OnDragStartLocal"
@ondragend="@OnDragEndLocal"
@ondragenter="@OnDragEnter"
@ondragenter:preventDefault="true"
@ondragover="@OnDragOver"
@ondragover:preventDefault="true"
@ondragleave="@OnDragLeave"
@ondrop="@OnDrop"
@ondrop:preventDefault="true"
style="width: 100%; cursor: pointer;">
<MudStack Row="true" Spacing="0" AlignItems="AlignItems.Center" Style="width: 100%; padding: 4px 8px; border-radius: 4px;" Class="folder-item-row">
@if (Item.Type == TreeItemType.Folder)
{
<MudIcon Icon="@(Item.IsExpanded ? Icons.Material.Filled.KeyboardArrowDown : Icons.Material.Filled.KeyboardArrowRight)"
Size="Size.Small"
Class="mr-1"
Style="width: 20px;" />
}
else
{
<div style="width: 20px;" class="mr-1"></div>
}
<MudIcon Icon="@(Item.Type == TreeItemType.Folder
? (Item.IsExpanded ? Icons.Material.Filled.FolderOpen : Icons.Material.Filled.Folder)
: Icons.Material.Filled.Description)"
Size="Size.Small"
Class="mr-2"
Color="@(Item.Type == TreeItemType.Folder ? Color.Warning : Color.Primary)"
Style="width: 20px;" />
<MudText Typo="Typo.body2" Class="flex-grow-1">
@Item.Name
</MudText>
</MudStack>
</div>
@if (Item.IsExpanded && Item.Children.Any())
{
<MudStack Spacing="0" Class="pl-4" Style="border-left: 1px solid var(--mud-palette-lines-default);">
@foreach (var child in Item.Children)
{
<FolderTreeItem Item="@child"
OnItemClick="@OnItemClick"
OnItemExpand="@OnItemExpand"
OnContextMenuWithArgs="@OnContextMenuWithArgs"
OnDragStart="@OnDragStartRecursive"
OnDragEnd="@OnDragEndRecursive"
OnItemDrop="@OnItemDropRecursive" />
}
</MudStack>
}
<style>
.folder-item:hover .folder-item-row {
background-color: var(--mud-palette-action-default-hover);
}
.folder-item.drag-source .folder-item-row {
opacity: 0.5;
}
.folder-item.drop-zone {
position: relative;
}
.folder-item.drop-zone-active > .folder-item-row {
background-color: var(--mud-palette-primary-hover);
outline: 2px dashed var(--mud-palette-primary);
outline-offset: -2px;
}
</style>
@code {
[Parameter] public TreeItemDto Item { get; set; } = null!;
[Parameter] public EventCallback<TreeItemDto> OnItemClick { get; set; }
[Parameter] public EventCallback<TreeItemDto> OnItemExpand { get; set; }
[Parameter] public EventCallback<(TreeItemDto, MouseEventArgs)> OnContextMenuWithArgs { get; set; }
[Parameter] public EventCallback<TreeItemDto> OnDragStart { get; set; }
[Parameter] public EventCallback<TreeItemDto> OnDragEnd { get; set; }
[Parameter] public EventCallback<TreeItemDto> OnItemDrop { get; set; }
private Task OnClick(TreeItemDto item)
{
return OnItemClick.InvokeAsync(item);
}
private async Task OnContextMenuHandler(MouseEventArgs args)
{
await OnContextMenuWithArgs.InvokeAsync((Item, args));
}
private async Task OnDragStartRecursive(TreeItemDto item)
{
await OnDragStart.InvokeAsync(item);
}
private async Task OnDragEndRecursive()
{
await OnDragEnd.InvokeAsync(Item);
}
private async Task OnItemDropRecursive(TreeItemDto item)
{
await OnItemDrop.InvokeAsync(item);
}
private async Task OnDragStartLocal()
{
await OnDragStart.InvokeAsync(Item);
}
private async Task OnDragEndLocal()
{
await OnDragEnd.InvokeAsync(Item);
}
private void OnDragEnter()
{
if (Item.Type == TreeItemType.Folder)
{
Item.IsDragOver = true;
}
}
private void OnDragOver(DragEventArgs args)
{
if (Item.Type == TreeItemType.Folder)
{
Item.IsDragOver = true;
}
}
private void OnDragLeave()
{
Item.IsDragOver = false;
}
private async Task OnDrop()
{
Item.IsDragOver = false;
await OnItemDrop.InvokeAsync(Item);
}
}