Refactor document upload handling

Replaced `UploadDocumentRequest` with `UploadDocument` class to streamline data management. Updated `EditForm` to bind directly to the new model, removing the `EditContext` and `HandleFileSelected` method. Adjusted validation and submission logic to work with the new structure, enhancing clarity and maintainability.
This commit is contained in:
Marco Minerva
2025-03-11 17:27:07 +01:00
parent e3dcf95da7
commit 0a38de6497
@@ -13,7 +13,7 @@
Upload new document Upload new document
</h4> </h4>
<EditForm EditContext="@editContext" OnValidSubmit="HandleValidSubmit"> <EditForm Model="Model" Enhance OnValidSubmit="HandleValidSubmit">
<DataAnnotationsValidator /> <DataAnnotationsValidator />
<div class="row"> <div class="row">
@@ -24,7 +24,7 @@
<Icon Class="d-flex text-body-secondary" Name="IconName.InfoCircle"></Icon> <Icon Class="d-flex text-body-secondary" Name="IconName.InfoCircle"></Icon>
</Tooltip> </Tooltip>
</span> </span>
<InputFile class="form-control" OnChange="HandleFileSelected" accept=".pdf,.docx,.txt,.md" /> <InputFile class="form-control" OnChange="@((e) => Model.File = e.File)" accept=".pdf,.docx,.txt,.md" />
</div> </div>
</div> </div>
<div class="col-md-5 col-sm-5 col-5"> <div class="col-md-5 col-sm-5 col-5">
@@ -35,13 +35,13 @@
</Tooltip> </Tooltip>
Document ID Document ID
</span> </span>
<TextInput Placeholder="Enter a valid GUID or leave empty for auto-generation" @bind-Value="@uploadDocumentRequest.DocumentId" /> <TextInput Placeholder="Enter a valid GUID or leave empty for auto-generation" @bind-Value="@Model.DocumentId" />
</div> </div>
<ValidationMessage For="@(() => uploadDocumentRequest.DocumentId)" /> <ValidationMessage For="@(() => Model.DocumentId)" />
</div> </div>
<div class="col-md-2 col-sm-3 col-2"> <div class="col-md-2 col-sm-3 col-2">
<div class="d-grid gap-2"> <div class="d-grid gap-2">
<Button @ref="uploadButton" Type="ButtonType.Submit" Color="ButtonColor.Primary" To="#" Disabled="@(uploadDocumentRequest.File is null)"><Icon Name="IconName.Upload" /><span class="d-none d-lg-inline ps-3">Upload</span></Button> <Button @ref="uploadButton" Type="ButtonType.Submit" Color="ButtonColor.Primary" To="#" Disabled="@(Model.File is null)"><Icon Name="IconName.Upload" /><span class="d-none d-lg-inline ps-3">Upload</span></Button>
</div> </div>
</div> </div>
</div> </div>
@@ -107,18 +107,11 @@ else
private bool isLoading = true; private bool isLoading = true;
private IList<SelectableDocument> documents = []; private IList<SelectableDocument> documents = [];
private UploadDocumentRequest uploadDocumentRequest = new(); private UploadDocument Model { get; set; } = new();
private EditContext? editContext;
[Inject] [Inject]
protected ToastService ToastService { get; set; } = default!; protected ToastService ToastService { get; set; } = default!;
protected override void OnInitialized()
{
editContext = new EditContext(uploadDocumentRequest);
base.OnInitialized();
}
protected override async Task OnAfterRenderAsync(bool firstRender) protected override async Task OnAfterRenderAsync(bool firstRender)
{ {
if (!firstRender) if (!firstRender)
@@ -156,31 +149,26 @@ else
} }
} }
private void HandleFileSelected(InputFileChangeEventArgs e)
{
uploadDocumentRequest.File = e.File;
}
private async Task HandleValidSubmit() private async Task HandleValidSubmit()
{ {
if (uploadDocumentRequest.File is null) if (Model.File is null)
{ {
return; return;
} }
uploadButton.ShowLoading(); uploadButton.ShowLoading();
var fileName = uploadDocumentRequest.File.Name; var fileName = Model.File.Name;
try try
{ {
await using var inputStream = uploadDocumentRequest.File.OpenReadStream(20 * 1024 * 1024); // 20 MB await using var inputStream = Model.File.OpenReadStream(20 * 1024 * 1024); // 20 MB
await using var stream = await inputStream.GetMemoryStreamAsync(); await using var stream = await inputStream.GetMemoryStreamAsync();
await using var scope = ServiceProvider.CreateAsyncScope(); await using var scope = ServiceProvider.CreateAsyncScope();
var vectorSearchService = scope.ServiceProvider.GetRequiredService<VectorSearchService>(); var vectorSearchService = scope.ServiceProvider.GetRequiredService<VectorSearchService>();
var documentId = string.IsNullOrWhiteSpace(uploadDocumentRequest.DocumentId) ? null : (Guid?)Guid.Parse(uploadDocumentRequest.DocumentId); var documentId = string.IsNullOrWhiteSpace(Model.DocumentId) ? null : (Guid?)Guid.Parse(Model.DocumentId);
await vectorSearchService.ImportAsync(stream, fileName, MimeUtility.GetMimeMapping(fileName), documentId); await vectorSearchService.ImportAsync(stream, fileName, MimeUtility.GetMimeMapping(fileName), documentId);
ToastService.Notify(await CreateToastMessageAsync(ToastType.Success, "Upload document", $"The document {fileName} has been successfully uploaded and indexed.")); ToastService.Notify(await CreateToastMessageAsync(ToastType.Success, "Upload document", $"The document {fileName} has been successfully uploaded and indexed."));
@@ -269,9 +257,8 @@ else
public string LocalCreationDateString { get; set; } = string.Empty; public string LocalCreationDateString { get; set; } = string.Empty;
} }
public class UploadDocumentRequest public class UploadDocument
{ {
[SupplyParameterFromForm]
public IBrowserFile? File { get; set; } public IBrowserFile? File { get; set; }
[RegularExpression(@"^(\{|\()?[0-9a-fA-F]{8}(-?)[0-9a-fA-F]{4}(-?)[0-9a-fA-F]{4}(-?)[0-9a-fA-F]{4}(-?)[0-9a-fA-F]{12}(\}|\))?$", ErrorMessage = "Invalid GUID format.")] [RegularExpression(@"^(\{|\()?[0-9a-fA-F]{8}(-?)[0-9a-fA-F]{4}(-?)[0-9a-fA-F]{4}(-?)[0-9a-fA-F]{4}(-?)[0-9a-fA-F]{12}(\}|\))?$", ErrorMessage = "Invalid GUID format.")]