Added ability to modify image of existing items
This commit is contained in:
@@ -15,6 +15,7 @@
|
|||||||
Route="Item"
|
Route="Item"
|
||||||
Scope="self">
|
Scope="self">
|
||||||
<Parameter Key="Name" Value="{Binding Name}" />
|
<Parameter Key="Name" Value="{Binding Name}" />
|
||||||
|
<Parameter Key="Category" Value="{Binding Category}" />
|
||||||
<Parameter Key="ImageDescriptor" Value="{Binding ImageDescriptor}" />
|
<Parameter Key="ImageDescriptor" Value="{Binding ImageDescriptor}" />
|
||||||
<Parameter Key="FromCategory" Value="{x:False}" />
|
<Parameter Key="FromCategory" Value="{x:False}" />
|
||||||
<Parameter Key="Favourite" Value="{Binding IsFavourite}" />
|
<Parameter Key="Favourite" Value="{Binding IsFavourite}" />
|
||||||
|
|||||||
@@ -16,11 +16,6 @@ public class WalletContext(DbContextOptions<WalletContext> options) :
|
|||||||
modelBuilder.Entity<ItemEntry>()
|
modelBuilder.Entity<ItemEntry>()
|
||||||
.HasKey(x => x.Id);
|
.HasKey(x => x.Id);
|
||||||
|
|
||||||
modelBuilder.Entity<ItemEntry>()
|
|
||||||
.Property(x => x.Id)
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasDefaultValueSql("NEWID()");
|
|
||||||
|
|
||||||
modelBuilder.Entity<ItemEntry>()
|
modelBuilder.Entity<ItemEntry>()
|
||||||
.HasMany(x => x.Tags)
|
.HasMany(x => x.Tags)
|
||||||
.WithOne()
|
.WithOne()
|
||||||
@@ -40,10 +35,5 @@ public class WalletContext(DbContextOptions<WalletContext> options) :
|
|||||||
|
|
||||||
modelBuilder.Entity<BlobEntry>()
|
modelBuilder.Entity<BlobEntry>()
|
||||||
.HasKey(x => x.Id);
|
.HasKey(x => x.Id);
|
||||||
|
|
||||||
modelBuilder.Entity<BlobEntry>()
|
|
||||||
.Property(x => x.Id)
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasDefaultValueSql("NEWID()");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -24,8 +24,8 @@ public class ConfirmCreateItemHandler(IMediator mediator,
|
|||||||
ItemConfiguration)>((id, name, category, imageDescriptor ?? default, itemConfiguration)));
|
ItemConfiguration)>((id, name, category, imageDescriptor ?? default, itemConfiguration)));
|
||||||
|
|
||||||
Item<(Guid, string, string)> item = new((id, name, category));
|
Item<(Guid, string, string)> item = new((id, name, category));
|
||||||
publisher.Publish(Created.As(item));
|
|
||||||
|
|
||||||
|
publisher.Publish(Created.As(item));
|
||||||
publisher.Publish(Changed.As<Item>());
|
publisher.Publish(Changed.As<Item>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,22 +15,26 @@ public class ConfirmUpdateItemHandler(IDecoratorService<Item<(Guid, string)>> it
|
|||||||
itemHeaderConfiguration.Service is ItemHeaderConfiguration headerConfiguration &&
|
itemHeaderConfiguration.Service is ItemHeaderConfiguration headerConfiguration &&
|
||||||
itemConfigurationDecorator.Service is ItemConfiguration itemConfiguration)
|
itemConfigurationDecorator.Service is ItemConfiguration itemConfiguration)
|
||||||
{
|
{
|
||||||
string? name = headerConfiguration?.Name;
|
if (headerConfiguration?.Name is { Length: > 0 } name &&
|
||||||
if (name is not null)
|
headerConfiguration.Category is { Length: > 0 } category)
|
||||||
{
|
{
|
||||||
publisher.Publish(Notify.As(new ItemHeader<string>(name)));
|
IImageDescriptor? imageDescriptor = headerConfiguration.ImageDescriptor;
|
||||||
|
|
||||||
(Guid id, string _) = item.Value;
|
publisher.Publish(Notify.As(new Item<string>(name)));
|
||||||
|
publisher.Publish(Notify.As(new Item<IImageDescriptor?>(imageDescriptor)));
|
||||||
|
|
||||||
|
(Guid id, _) = item.Value;
|
||||||
|
|
||||||
|
await mediator.Handle<UpdateEventArgs<Item<(Guid, string, string, IImageDescriptor?,
|
||||||
|
ItemConfiguration)>>, bool>(new UpdateEventArgs<Item<(Guid, string, string, IImageDescriptor?,
|
||||||
|
ItemConfiguration)>>(new Item<(Guid, string, string, IImageDescriptor?, ItemConfiguration)>((id,
|
||||||
|
name, category, imageDescriptor, itemConfiguration))));
|
||||||
|
|
||||||
Item<(Guid, string)> newItem = new((id, name));
|
Item<(Guid, string)> newItem = new((id, name));
|
||||||
publisher.Publish(Modified.As(item, newItem));
|
publisher.Publish(Modified.As(item, newItem));
|
||||||
|
|
||||||
itemDecorator.Set(newItem);
|
itemDecorator.Set(newItem);
|
||||||
|
publisher.Publish(Changed.As(newItem));
|
||||||
await mediator.Handle<UpdateEventArgs<Item<(Guid, string, ItemConfiguration)>>, bool>(new UpdateEventArgs<Item<(Guid, string,
|
|
||||||
ItemConfiguration)>>(new Item<(Guid, string, ItemConfiguration)>((id, name, itemConfiguration))));
|
|
||||||
|
|
||||||
publisher.Publish(Changed.As(item));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ public class CreateItemHandler(IImageWriter imageWriter,
|
|||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
(Guid id, string name, string category, IImageDescriptor? imageDescriptor, ItemConfiguration configuration) = args.Sender;
|
(Guid id, string name, string category, IImageDescriptor? imageDescriptor, ItemConfiguration configuration) = args.Sender;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string content = JsonSerializer.Serialize(configuration);
|
string content = JsonSerializer.Serialize(configuration);
|
||||||
|
|||||||
@@ -41,7 +41,8 @@ public partial class ItemHeaderViewModel :
|
|||||||
Value = value;
|
Value = value;
|
||||||
ImageDescriptor = imageDescriptor;
|
ImageDescriptor = imageDescriptor;
|
||||||
|
|
||||||
Track(nameof(Value), () => Value, newValue => Value = newValue);
|
Track(nameof(Value), () => Value, x => Value = x);
|
||||||
|
Track(nameof(ImageDescriptor), () => ImageDescriptor, x => ImageDescriptor = x);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task Handle(UpdateEventArgs<Item> args) =>
|
public Task Handle(UpdateEventArgs<Item> args) =>
|
||||||
@@ -74,29 +75,6 @@ public partial class ItemHeaderViewModel :
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
|
||||||
private async Task Import() => ImageDescriptor = await Mediator.Handle<CreateEventArgs<ProfileImage>,
|
|
||||||
IImageDescriptor>(Create.As<ProfileImage>());
|
|
||||||
|
|
||||||
[RelayCommand]
|
|
||||||
private void Remove() => ImageDescriptor = null;
|
|
||||||
|
|
||||||
protected override void OnValueChanged()
|
|
||||||
{
|
|
||||||
if (configuration is not null)
|
|
||||||
{
|
|
||||||
configuration.Name = Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
partial void OnImageDescriptorChanging(IImageDescriptor? value)
|
|
||||||
{
|
|
||||||
if (configuration is not null)
|
|
||||||
{
|
|
||||||
configuration.ImageDescriptor = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task Handle(NotifyEventArgs<Item<IImageDescriptor>> args)
|
public Task Handle(NotifyEventArgs<Item<IImageDescriptor>> args)
|
||||||
{
|
{
|
||||||
if (args.Sender is Item<IImageDescriptor> item)
|
if (args.Sender is Item<IImageDescriptor> item)
|
||||||
@@ -106,4 +84,46 @@ public partial class ItemHeaderViewModel :
|
|||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnValueChanged()
|
||||||
|
{
|
||||||
|
if (configuration is not null)
|
||||||
|
{
|
||||||
|
configuration.Name = Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private async Task Import() => ImageDescriptor = await Mediator.Handle<CreateEventArgs<ProfileImage>,
|
||||||
|
IImageDescriptor>(Create.As<ProfileImage>());
|
||||||
|
|
||||||
|
partial void OnImageDescriptorChanged(IImageDescriptor? value)
|
||||||
|
{
|
||||||
|
if (configuration is not null)
|
||||||
|
{
|
||||||
|
configuration.ImageDescriptor = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
partial void OnImageDescriptorChanged(IImageDescriptor? oldValue,
|
||||||
|
IImageDescriptor? newValue)
|
||||||
|
{
|
||||||
|
if (configuration is not null)
|
||||||
|
{
|
||||||
|
if (State is ItemState.Write)
|
||||||
|
{
|
||||||
|
if (newValue != oldValue)
|
||||||
|
{
|
||||||
|
configuration.ImageDescriptor = newValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
configuration.ImageDescriptor = newValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void Remove() => ImageDescriptor = null;
|
||||||
}
|
}
|
||||||
@@ -25,7 +25,7 @@ public partial class ItemNavigationViewModel(IServiceProvider provider,
|
|||||||
INotificationHandler<FavouriteEventArgs<Item>>,
|
INotificationHandler<FavouriteEventArgs<Item>>,
|
||||||
INotificationHandler<UnfavouriteEventArgs<Item>>,
|
INotificationHandler<UnfavouriteEventArgs<Item>>,
|
||||||
INotificationHandler<DeleteEventArgs<Item>>,
|
INotificationHandler<DeleteEventArgs<Item>>,
|
||||||
INotificationHandler<NotifyEventArgs<ItemHeader<string>>>,
|
INotificationHandler<NotifyEventArgs<Item<string>>>,
|
||||||
INotificationHandler<NotifyEventArgs<Item<IImageDescriptor>>>,
|
INotificationHandler<NotifyEventArgs<Item<IImageDescriptor>>>,
|
||||||
IKeyed<Guid>,
|
IKeyed<Guid>,
|
||||||
ISelectable,
|
ISelectable,
|
||||||
@@ -45,11 +45,13 @@ public partial class ItemNavigationViewModel(IServiceProvider provider,
|
|||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private bool isArchived = isArchived;
|
private bool isArchived = isArchived;
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private bool isAttached;
|
private bool isAttached;
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private bool isFavourite = isFavourite;
|
private bool isFavourite = isFavourite;
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private bool isSelected = isSelected;
|
private bool isSelected = isSelected;
|
||||||
|
|
||||||
@@ -84,9 +86,9 @@ public partial class ItemNavigationViewModel(IServiceProvider provider,
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task Handle(NotifyEventArgs<ItemHeader<string>> args)
|
public Task Handle(NotifyEventArgs<Item<string>> args)
|
||||||
{
|
{
|
||||||
if (args.Sender is ItemHeader<string> header)
|
if (args.Sender is Item<string> header)
|
||||||
{
|
{
|
||||||
Name = header.Value;
|
Name = header.Value;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ public partial class ItemViewModel :
|
|||||||
NamedComponent named,
|
NamedComponent named,
|
||||||
IDecoratorService<ItemHeaderConfiguration> itemHeaderConfigurationDecorator,
|
IDecoratorService<ItemHeaderConfiguration> itemHeaderConfigurationDecorator,
|
||||||
string name = "",
|
string name = "",
|
||||||
|
string category = "",
|
||||||
ImageDescriptor? imageDescriptor = null,
|
ImageDescriptor? imageDescriptor = null,
|
||||||
bool fromCategory = false,
|
bool fromCategory = false,
|
||||||
bool favourite = false,
|
bool favourite = false,
|
||||||
@@ -53,7 +54,8 @@ public partial class ItemViewModel :
|
|||||||
|
|
||||||
ItemHeaderConfiguration configuration = new()
|
ItemHeaderConfiguration configuration = new()
|
||||||
{
|
{
|
||||||
Name = name
|
Name = name,
|
||||||
|
Category = category,
|
||||||
};
|
};
|
||||||
|
|
||||||
itemHeaderConfigurationDecorator.Set(configuration);
|
itemHeaderConfigurationDecorator.Set(configuration);
|
||||||
|
|||||||
@@ -6,20 +6,22 @@ using Toolkit.Foundation;
|
|||||||
|
|
||||||
namespace Wallet;
|
namespace Wallet;
|
||||||
|
|
||||||
public class UpdateItemHander(IDbContextFactory<WalletContext> dbContextFactory) :
|
public class UpdateItemHander(IDbContextFactory<WalletContext> dbContextFactory,
|
||||||
IHandler<UpdateEventArgs<Item<(Guid, string, ItemConfiguration)>>, bool>
|
IImageWriter imageWriter) :
|
||||||
|
IHandler<UpdateEventArgs<Item<(Guid, string, string, IImageDescriptor?, ItemConfiguration)>>, bool>
|
||||||
{
|
{
|
||||||
public async Task<bool> Handle(UpdateEventArgs<Item<(Guid, string, ItemConfiguration)>> args,
|
public async Task<bool> Handle(UpdateEventArgs<Item<(Guid, string, string, IImageDescriptor?, ItemConfiguration)>> args,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (args.Sender is Item<(Guid, string, ItemConfiguration)> item)
|
if (args.Sender is Item<(Guid, string, string, IImageDescriptor?, ItemConfiguration)> item)
|
||||||
{
|
{
|
||||||
(Guid id, string name, ItemConfiguration configuration) = item.Value;
|
(Guid id, string name, string category, IImageDescriptor? imageDescriptor, ItemConfiguration configuration) = item.Value;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using WalletContext context = await dbContextFactory.CreateDbContextAsync(cancellationToken);
|
using WalletContext context = await dbContextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
ItemEntry? result = result = await context.Set<ItemEntry>().FindAsync([id], cancellationToken);
|
ItemEntry? result = result = await context.Set<ItemEntry>()
|
||||||
|
.Include(x => x.Image).FirstOrDefaultAsync(x => x.Id == id, cancellationToken);
|
||||||
|
|
||||||
if (result is not null)
|
if (result is not null)
|
||||||
{
|
{
|
||||||
@@ -31,7 +33,45 @@ public class UpdateItemHander(IDbContextFactory<WalletContext> dbContextFactory)
|
|||||||
Type = 0,
|
Type = 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (imageDescriptor is not null)
|
||||||
|
{
|
||||||
|
byte[]? thumbData = null;
|
||||||
|
using MemoryStream memoryStream = new();
|
||||||
|
imageWriter.Write(imageDescriptor, memoryStream);
|
||||||
|
thumbData = memoryStream.ToArray();
|
||||||
|
|
||||||
|
if (result.Image is BlobEntry existingImageBlob)
|
||||||
|
{
|
||||||
|
existingImageBlob.Data = thumbData;
|
||||||
|
existingImageBlob.DateTime = DateTime.UtcNow;
|
||||||
|
|
||||||
|
context.Entry(result.Image).State = EntityState.Modified;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.Image = new BlobEntry
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
Data = thumbData,
|
||||||
|
DateTime = DateTime.UtcNow,
|
||||||
|
Type = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
context.Entry(result.Image).State = EntityState.Added;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (result.Image is not null)
|
||||||
|
{
|
||||||
|
context.Remove(result.Image);
|
||||||
|
result.Image = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
result.Name = name;
|
result.Name = name;
|
||||||
|
result.Category = category;
|
||||||
|
|
||||||
await context.SaveChangesAsync(cancellationToken);
|
await context.SaveChangesAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ public partial class WalletHeaderViewModel(IServiceProvider provider,
|
|||||||
public Task Handle(NotifyEventArgs<WalletCommandHeaderCollection> args)
|
public Task Handle(NotifyEventArgs<WalletCommandHeaderCollection> args)
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
|
|
||||||
if (args.Sender is WalletCommandHeaderCollection commandCollection)
|
if (args.Sender is WalletCommandHeaderCollection commandCollection)
|
||||||
{
|
{
|
||||||
foreach (IDisposable command in commandCollection)
|
foreach (IDisposable command in commandCollection)
|
||||||
|
|||||||
Reference in New Issue
Block a user