4 Commits

Author SHA1 Message Date
khwezi 66081eead5 Merge pull request 'Added image deletion functionality to product creation' (#20) from products into master
Reviewed-on: #20
2026-05-20 16:12:55 +02:00
Khwezi Mngoma 530b8ffea2 Added image deletion functionality to product creation
continuous-integration/drone/pr Build is passing
2026-05-20 16:12:10 +02:00
khwezi b8a5d81856 Merge pull request 'Fixed manifest ev variable reference syntax' (#19) from products into master
Reviewed-on: #19
2026-05-20 13:42:27 +02:00
Khwezi Mngoma 5c34663617 Fixed manifest ev variable reference syntax
continuous-integration/drone/pr Build is passing
2026-05-20 13:41:31 +02:00
3 changed files with 56 additions and 37 deletions
+46 -29
View File
@@ -1,6 +1,4 @@
using LiteCharms.Features.S3.Abstractions;
using Microsoft.AspNetCore.Components.Forms;
using System.ComponentModel.DataAnnotations;
using static LiteCharms.Features.S3.Constants;
namespace ShopAdmin.Components;
@@ -16,6 +14,8 @@ public partial class CreateProduct([FromKeyedServices(BookshopBucketName)] IS3Se
private const long MaxAllowedFileSize = 1024 * 1024 * 5;
private readonly Func<string, string> GetFileKeyFromUrl = url => url.Split('/').Last();
protected override void OnInitialized()
{
base.OnInitialized();
@@ -26,15 +26,11 @@ public partial class CreateProduct([FromKeyedServices(BookshopBucketName)] IS3Se
ProductModel.Thumbnails = [.. Enumerable.Repeat(string.Empty, 5)];
}
// Your saving logic goes here when the ledger button is clicked
public Task HandleValidSubmit() => Task.CompletedTask;
// Checks if a valid URL asset exists at the specified position
public bool HasAssetAt(int index) => ProductModel?.Thumbnails == null || index >= ProductModel.Thumbnails.Count
? false
: !string.IsNullOrWhiteSpace(ProductModel.Thumbnails[index]);
public bool HasAssetAt(int index) => (ProductModel?.Thumbnails) != null && index < ProductModel.Thumbnails.Count &&
!string.IsNullOrWhiteSpace(ProductModel.Thumbnails[index]);
// Handles uploading the primary image node
private async Task HandleMainImageUpload(InputFileChangeEventArgs e)
{
try
@@ -47,7 +43,9 @@ public partial class CreateProduct([FromKeyedServices(BookshopBucketName)] IS3Se
await file.OpenReadStream(MaxAllowedFileSize).CopyToAsync(stream, cancellationToken);
var result = await s3Service.UploadFileAsync(file.Name,stream,
stream.Seek(0, SeekOrigin.Begin);
var result = await s3Service.UploadFileAsync(file.Name, stream,
MimeTypes.GetMimeType(file.Name), cancellationToken);
if (result.IsSuccess)
@@ -65,20 +63,20 @@ public partial class CreateProduct([FromKeyedServices(BookshopBucketName)] IS3Se
public void SetPreviewActive(string? url)
{
if (!string.IsNullOrWhiteSpace(url))
{
ActivePreviewUrl = url;
StateHasChanged();
}
if (string.IsNullOrWhiteSpace(url)) return;
ActivePreviewUrl = url;
StateHasChanged();
}
public void ClosePreviewDrawer()
{
ActivePreviewUrl = null;
StateHasChanged();
}
// Handles uploading a thumbnail image into its specific slot index
private async Task HandleThumbnailUpload(InputFileChangeEventArgs e, int index)
{
try
@@ -91,6 +89,8 @@ public partial class CreateProduct([FromKeyedServices(BookshopBucketName)] IS3Se
await file.OpenReadStream(MaxAllowedFileSize, cancellationToken).CopyToAsync(stream, cancellationToken);
stream.Seek(0, SeekOrigin.Begin);
var result = await s3Service.UploadFileAsync(file.Name, stream,
MimeTypes.GetMimeType(file.Name), cancellationToken);
@@ -107,25 +107,42 @@ public partial class CreateProduct([FromKeyedServices(BookshopBucketName)] IS3Se
}
}
public void ClearMainImage()
public async Task ClearMainImage()
{
if (ActivePreviewUrl == ProductModel.ImageUrl)
{
ActivePreviewUrl = null;
}
if (string.IsNullOrEmpty(ProductModel.ImageUrl)) return;
var targetUrl = ProductModel.ImageUrl;
if (ActivePreviewUrl == targetUrl) ActivePreviewUrl = null;
ProductModel.ImageUrl = null;
StateHasChanged();
var result = await s3Service.DeleteFileAsync(GetFileKeyFromUrl(targetUrl));
if (!result.IsSuccess)
Console.WriteLine($"[S3 Orphan Cleanup Failure]: {result.Errors[0].Message}");
}
public void RemoveThumbnailAt(int index)
public async Task RemoveThumbnailAt(int index)
{
if (index >= 0 && index < ProductModel.Thumbnails.Count)
{
if (ActivePreviewUrl == ProductModel.Thumbnails[index])
{
ActivePreviewUrl = null;
}
ProductModel.Thumbnails[index] = string.Empty;
}
if (index < 0 || index >= ProductModel.Thumbnails.Count) return;
var targetUrl = ProductModel.Thumbnails[index];
if (string.IsNullOrEmpty(targetUrl)) return;
if (ActivePreviewUrl == targetUrl) ActivePreviewUrl = null;
ProductModel.Thumbnails[index] = string.Empty;
StateHasChanged();
var result = await s3Service.DeleteFileAsync(GetFileKeyFromUrl(targetUrl));
if (result.IsFailed)
Console.WriteLine($"[S3 Thumbnail Cleanup Failure]: {result.Errors[0].Message}");
}
}
+3 -1
View File
@@ -16,7 +16,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="LiteCharms.Features" Version="1.39.0" />
<PackageReference Include="LiteCharms.Features" Version="1.40.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.QuickGrid" Version="10.0.8" />
<PackageReference Include="Polly" Version="8.6.6" />
</ItemGroup>
@@ -59,6 +59,8 @@
<!-- Shared Global Usings -->
<ItemGroup>
<Using Include="MimeKit" />
<Using Include="System.ComponentModel.DataAnnotations" />
<Using Include="Microsoft.AspNetCore.Components.Forms" />
<Using Include="Microsoft.AspNetCore.Components.QuickGrid" />
<Using Include="Microsoft.AspNetCore.HttpOverrides" />
<Using Include="Microsoft.AspNetCore.Authentication" />
+6 -6
View File
@@ -86,14 +86,14 @@ spec:
env:
- name: BookshopS3Settings__AccessKey
valueFrom:
secretKeyRef:
name: shopadmin-secrets
key: bookshop-s3-accesskey
secretKeyRef:
name: shopadmin-secrets
key: bookshop-s3-accesskey
- name: BookshopS3Settings__SecretKey
valueFrom:
secretKeyRef:
name: shopadmin-secrets
key: bookshop-s3-secretkey
secretKeyRef:
name: shopadmin-secrets
key: bookshop-s3-secretkey
- name: ConnectionStrings__PostgresScheduler
valueFrom:
secretKeyRef: