Add ability to fully delete items from the DB

This commit is contained in:
TheXamlGuy
2024-06-23 09:58:19 +01:00
parent 95de9d187f
commit db20ee15cc
18 changed files with 98 additions and 22 deletions
+1 -1
Submodule Toolkit updated: 4a33a1931f...f993e1d44b
+3 -1
View File
@@ -105,6 +105,7 @@ public partial class App : Application
services.AddHandler<QueryWalletHandler>(); services.AddHandler<QueryWalletHandler>();
services.AddHandler<RequestItemHandler>(); services.AddHandler<RequestItemHandler>();
services.AddHandler<CreateItemHandler>(); services.AddHandler<CreateItemHandler>();
services.AddHandler<DeleteItemHandler>();
services.AddHandler<UpdateItemHander>(); services.AddHandler<UpdateItemHander>();
services.AddHandler<UpdateItemStateHandler>(); services.AddHandler<UpdateItemStateHandler>();
services.AddHandler<CountCategoriesHandler>(); services.AddHandler<CountCategoriesHandler>();
@@ -181,7 +182,8 @@ public partial class App : Application
services.AddHandler<ConfirmUpdateItemHandler>(nameof(ItemState.Write)); services.AddHandler<ConfirmUpdateItemHandler>(nameof(ItemState.Write));
services.AddHandler<ConfirmCreateItemHandler>(nameof(ItemState.New)); services.AddHandler<ConfirmCreateItemHandler>(nameof(ItemState.New));
services.AddHandler<ConfirmDeleteItemHandler>();
services.AddHandler<HyperlinkHandler>(); services.AddHandler<HyperlinkHandler>();
services.AddHandler<ItemChangedHandler>(ServiceLifetime.Singleton); services.AddHandler<ItemChangedHandler>(ServiceLifetime.Singleton);
+1 -1
View File
@@ -16,7 +16,7 @@
Margin="0,3,0,0" Margin="0,3,0,0"
VerticalAlignment="Center" VerticalAlignment="Center"
FontFamily="{DynamicResource FluentThemeFontFamily}" FontFamily="{DynamicResource FluentThemeFontFamily}"
FontSize="16" FontSize="18"
Foreground="{DynamicResource IconForegroundBrush}" Foreground="{DynamicResource IconForegroundBrush}"
Text="&#xE073;" /> Text="&#xE073;" />
</Button> </Button>
+1 -1
View File
@@ -15,7 +15,7 @@
Margin="0,3,0,0" Margin="0,3,0,0"
VerticalAlignment="Center" VerticalAlignment="Center"
FontFamily="{DynamicResource FluentThemeFontFamily}" FontFamily="{DynamicResource FluentThemeFontFamily}"
FontSize="16" FontSize="18"
Foreground="{DynamicResource IconForegroundBrush}" Foreground="{DynamicResource IconForegroundBrush}"
Text="&#xE3EA;" /> Text="&#xE3EA;" />
</Button> </Button>
+3 -3
View File
@@ -14,9 +14,9 @@
<TextBlock <TextBlock
Margin="0,3,0,0" Margin="0,3,0,0"
VerticalAlignment="Center" VerticalAlignment="Center"
FontFamily="{DynamicResource SymbolThemeFontFamily}" FontFamily="{DynamicResource FluentThemeFontFamily}"
FontSize="16" FontSize="18"
Foreground="{DynamicResource IconForegroundBrush}" Foreground="{DynamicResource IconForegroundBrush}"
Text="&#xE107;" /> Text="&#xE5B9;" />
</Button> </Button>
</UserControl> </UserControl>
+1 -1
View File
@@ -15,7 +15,7 @@
Margin="0,3,0,0" Margin="0,3,0,0"
VerticalAlignment="Center" VerticalAlignment="Center"
FontFamily="{DynamicResource FluentThemeFontFamily}" FontFamily="{DynamicResource FluentThemeFontFamily}"
FontSize="16" FontSize="18"
Foreground="{DynamicResource IconForegroundBrush}" Foreground="{DynamicResource IconForegroundBrush}"
Text="&#xE607;" /> Text="&#xE607;" />
</Button> </Button>
+1 -1
View File
@@ -15,7 +15,7 @@
Margin="0,3,0,0" Margin="0,3,0,0"
VerticalAlignment="Center" VerticalAlignment="Center"
FontFamily="{DynamicResource FluentThemeFontFamily}" FontFamily="{DynamicResource FluentThemeFontFamily}"
FontSize="16" FontSize="18"
Foreground="{DynamicResource IconForegroundBrush}" Foreground="{DynamicResource IconForegroundBrush}"
Text="&#xE759;" /> Text="&#xE759;" />
</Button> </Button>
@@ -14,14 +14,14 @@
<TextBlock <TextBlock
VerticalAlignment="Center" VerticalAlignment="Center"
FontFamily="{DynamicResource FluentThemeFontFamily}" FontFamily="{DynamicResource FluentThemeFontFamily}"
FontSize="16" FontSize="18"
Foreground="{DynamicResource IconForegroundBrush}" Foreground="{DynamicResource IconForegroundBrush}"
IsVisible="{Binding !Value}" IsVisible="{Binding !Value}"
Text="&#xEF61;" /> Text="&#xEF61;" />
<TextBlock <TextBlock
VerticalAlignment="Center" VerticalAlignment="Center"
FontFamily="{DynamicResource FluentThemeFontFamily}" FontFamily="{DynamicResource FluentThemeFontFamily}"
FontSize="16" FontSize="18"
Foreground="{DynamicResource IconForegroundBrush}" Foreground="{DynamicResource IconForegroundBrush}"
IsVisible="{Binding Value}" IsVisible="{Binding Value}"
Text="&#xEF60;" /> Text="&#xEF60;" />
+5
View File
@@ -5,6 +5,11 @@
xmlns:vm="using:Wallet" xmlns:vm="using:Wallet"
x:DataType="vm:ItemSectionViewModel"> x:DataType="vm:ItemSectionViewModel">
<ItemsControl ItemTemplate="{ReflectionBinding Template}" ItemsSource="{Binding}"> <ItemsControl ItemTemplate="{ReflectionBinding Template}" ItemsSource="{Binding}">
<ItemsControl.Styles>
<Style Selector="ContentPresenter">
<Setter Property="IsTabStop" Value="False" />
</Style>
</ItemsControl.Styles>
<ItemsControl.ItemsPanel> <ItemsControl.ItemsPanel>
<ItemsPanelTemplate> <ItemsPanelTemplate>
<StackPanel Orientation="Vertical" Spacing="4" /> <StackPanel Orientation="Vertical" Spacing="4" />
+7
View File
@@ -2,8 +2,15 @@
x:Class="Wallet.Avalonia.ItemView" x:Class="Wallet.Avalonia.ItemView"
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ui="using:FluentAvalonia.UI.Controls"
xmlns:vm="using:Wallet" xmlns:vm="using:Wallet"
x:DataType="vm:ItemViewModel"> x:DataType="vm:ItemViewModel">
<UserControl.Styles>
<Style Selector="ui|SettingsExpander">
<Setter Property="IsTabStop" Value="False" />
<Setter Property="KeyboardNavigation.TabNavigation" Value="Local" />
</Style>
</UserControl.Styles>
<Interaction.Behaviors> <Interaction.Behaviors>
<AttachedBehaviour> <AttachedBehaviour>
<NavigateAction <NavigateAction
@@ -10,12 +10,12 @@
VerticalAlignment="Center" VerticalAlignment="Center"
Command="{Binding InvokeCommand}" Command="{Binding InvokeCommand}"
Foreground="{DynamicResource IconForegroundBrush}" Foreground="{DynamicResource IconForegroundBrush}"
ToolTip.Tip="Unarchive"> ToolTip.Tip="Restore">
<TextBlock <TextBlock
VerticalAlignment="Center" VerticalAlignment="Center"
FontFamily="{DynamicResource FluentThemeFontFamily}" FontFamily="{DynamicResource FluentThemeFontFamily}"
FontSize="16" FontSize="18"
Foreground="{DynamicResource IconForegroundBrush}" Foreground="{DynamicResource IconForegroundBrush}"
Text="&#xF1A0;" /> Text="&#xE075;" />
</Button> </Button>
</UserControl> </UserControl>
+4 -2
View File
@@ -15,10 +15,12 @@ public class WalletContext(DbContextOptions<WalletContext> options) :
{ {
modelBuilder.Entity<ItemEntry>() modelBuilder.Entity<ItemEntry>()
.HasMany(x => x.Tags) .HasMany(x => x.Tags)
.WithOne(); .WithOne()
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<ItemEntry>() modelBuilder.Entity<ItemEntry>()
.HasMany(x => x.Blobs) .HasMany(x => x.Blobs)
.WithOne(); .WithOne()
.OnDelete(DeleteBehavior.Cascade);
} }
} }
+30
View File
@@ -0,0 +1,30 @@
using Toolkit.Foundation;
namespace Wallet;
public class ConfirmDeleteItemHandler(IDecoratorService<Item<(Guid, string)>> decoratorService,
ICache<Item<(Guid, string)>> cache,
IMediator mediator,
IPublisher publisher) :
INotificationHandler<DeleteEventArgs<Item>>
{
public async Task Handle(DeleteEventArgs<Item> args)
{
try
{
if (decoratorService.Service is Item<(Guid, string)> item)
{
(Guid id, string name) = item.Value;
await mediator.Handle<DeleteEventArgs<Item<Guid>>,
bool>(new DeleteEventArgs<Item<Guid>>(new Item<Guid>(id)));
cache.Add(item);
publisher.Publish(Changed.As<Item>());
}
}
catch
{
}
}
}
+26
View File
@@ -0,0 +1,26 @@
using Microsoft.EntityFrameworkCore;
using Toolkit.Foundation;
using Wallet.Data;
namespace Wallet;
public class DeleteItemHandler(IDbContextFactory<WalletContext> dbContextFactory) :
IHandler<DeleteEventArgs<Item<Guid>>, bool>
{
public async Task<bool> Handle(DeleteEventArgs<Item<Guid>> args,
CancellationToken cancellationToken)
{
if (args.Sender is Item<Guid> item)
{
Guid id = item.Value;
using WalletContext context = await dbContextFactory.CreateDbContextAsync(cancellationToken);
if (await context.FindAsync<ItemEntry>(id) is ItemEntry result)
{
context.Items.Remove(result);
await context.SaveChangesAsync(cancellationToken);
}
}
return false;
}
}
+7 -4
View File
@@ -23,6 +23,7 @@ public partial class ItemNavigationViewModel(IServiceProvider provider,
INotificationHandler<UnarchiveEventArgs<Item>>, INotificationHandler<UnarchiveEventArgs<Item>>,
INotificationHandler<FavouriteEventArgs<Item>>, INotificationHandler<FavouriteEventArgs<Item>>,
INotificationHandler<UnfavouriteEventArgs<Item>>, INotificationHandler<UnfavouriteEventArgs<Item>>,
INotificationHandler<DeleteEventArgs<Item>>,
INotificationHandler<NotifyEventArgs<ItemHeader<string>>>, INotificationHandler<NotifyEventArgs<ItemHeader<string>>>,
IKeyed<Guid>, IKeyed<Guid>,
ISelectable, ISelectable,
@@ -43,15 +44,14 @@ public partial class ItemNavigationViewModel(IServiceProvider provider,
[ObservableProperty] [ObservableProperty]
private Guid id = id; private Guid id = id;
[ObservableProperty]
private bool isSelected = isSelected;
[ObservableProperty] [ObservableProperty]
private string? name = name; private string? name = name;
[ObservableProperty] [ObservableProperty]
private string named = $"{named}"; private string named = $"{named}";
[ObservableProperty]
private bool isSelected = isSelected;
public IContentTemplate Template { get; set; } = template; public IContentTemplate Template { get; set; } = template;
public Task Handle(ArchiveEventArgs<Item> args) => public Task Handle(ArchiveEventArgs<Item> args) =>
@@ -75,4 +75,7 @@ public partial class ItemNavigationViewModel(IServiceProvider provider,
return Task.CompletedTask; return Task.CompletedTask;
} }
public Task Handle(DeleteEventArgs<Item> args) =>
Task.Run(Dispose);
} }
+1
View File
@@ -108,6 +108,7 @@ public partial class ItemViewModel :
Publisher.Publish(Notify.As(Factory.Create<ItemCommandHeaderCollection>(new List<IDisposable> Publisher.Publish(Notify.As(Factory.Create<ItemCommandHeaderCollection>(new List<IDisposable>
{ {
Factory.Create<UnarchiveItemActionViewModel>(), Factory.Create<UnarchiveItemActionViewModel>(),
Factory.Create<DeleteItemActionViewModel>(),
}))); })));
} }
else else
+1 -1
View File
@@ -12,7 +12,7 @@ public class UpdateItemHander(IDbContextFactory<WalletContext> dbContextFactory)
public async Task<bool> Handle(UpdateEventArgs<Item<(Guid, string, ItemConfiguration)>> args, public async Task<bool> Handle(UpdateEventArgs<Item<(Guid, string, ItemConfiguration)>> args,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
if (args.Value is Item<(Guid, string, ItemConfiguration)> item) if (args.Sender is Item<(Guid, string, ItemConfiguration)> item)
{ {
(Guid id, string name, ItemConfiguration configuration) = item.Value; (Guid id, string name, ItemConfiguration configuration) = item.Value;
+1 -1
View File
@@ -10,7 +10,7 @@ public class UpdateItemStateHandler(IDbContextFactory<WalletContext> dbContextFa
public async Task<bool> Handle(UpdateEventArgs<(Guid, int)> args, public async Task<bool> Handle(UpdateEventArgs<(Guid, int)> args,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
if (args.Value is (Guid id, int state)) if (args.Sender is (Guid id, int state))
{ {
using WalletContext context = await dbContextFactory.CreateDbContextAsync(cancellationToken); using WalletContext context = await dbContextFactory.CreateDbContextAsync(cancellationToken);
if (await context.FindAsync<ItemEntry>(id) is ItemEntry result) if (await context.FindAsync<ItemEntry>(id) is ItemEntry result)