feat: get web app talking to api
This commit is contained in:
@@ -45,6 +45,21 @@ builder.Services.AddRateLimiter(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// TODO: Make CORS more restrictive
|
||||||
|
// only allow requests from the web
|
||||||
|
// client
|
||||||
|
const string corsPolicyName = "cors";
|
||||||
|
|
||||||
|
builder.Services.AddCors(o =>
|
||||||
|
{
|
||||||
|
o.AddPolicy(corsPolicyName, p =>
|
||||||
|
{
|
||||||
|
p.AllowAnyOrigin()
|
||||||
|
.AllowAnyOrigin()
|
||||||
|
.AllowAnyMethod();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
if (app.Environment.IsDevelopment())
|
if (app.Environment.IsDevelopment())
|
||||||
@@ -57,6 +72,8 @@ if (app.Environment.IsProduction())
|
|||||||
app.UseRateLimiter();
|
app.UseRateLimiter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app.UseCors(corsPolicyName);
|
||||||
|
|
||||||
app.UseHttpsRedirection();
|
app.UseHttpsRedirection();
|
||||||
|
|
||||||
app.UseStatusCodePages();
|
app.UseStatusCodePages();
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
namespace AltGen.Console.Generate;
|
namespace AltGen.Console.Generate;
|
||||||
|
|
||||||
|
// TODO: Use shared library version of this service
|
||||||
sealed class AltGenService(HttpClient client) : IAltGenService
|
sealed class AltGenService(HttpClient client) : IAltGenService
|
||||||
{
|
{
|
||||||
static readonly JsonSerializerOptions JsonOptions = new()
|
static readonly JsonSerializerOptions JsonOptions = new()
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace AltGen.Shared.Generate;
|
||||||
|
|
||||||
|
public sealed class AltGenService(HttpClient client) : IAltGenService
|
||||||
|
{
|
||||||
|
static readonly JsonSerializerOptions JsonOptions = new()
|
||||||
|
{
|
||||||
|
PropertyNameCaseInsensitive = true
|
||||||
|
};
|
||||||
|
readonly HttpClient _client = client;
|
||||||
|
|
||||||
|
public async Task<string> GenerateAltTextAsync(GenerateAltTextRequest req)
|
||||||
|
{
|
||||||
|
var byteContent = new ByteArrayContent(req.Image);
|
||||||
|
byteContent.Headers.ContentType = new MediaTypeHeaderValue(req.ContentType);
|
||||||
|
|
||||||
|
var request = new HttpRequestMessage(HttpMethod.Post, "/generate")
|
||||||
|
{
|
||||||
|
Content = new MultipartFormDataContent
|
||||||
|
{
|
||||||
|
{ new StringContent(req.Provider), "provider" },
|
||||||
|
{ new StringContent(req.ProviderKey), "providerKey" },
|
||||||
|
{ byteContent, "file", req.FileName }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var response = await _client.SendAsync(request);
|
||||||
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
if (response.IsSuccessStatusCode is false)
|
||||||
|
{
|
||||||
|
throw new AltTextException("Failed to generate alt text.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var altTextResponse = JsonSerializer.Deserialize<AltTextResponse>(content, JsonOptions) ?? throw new AltTextException("Failed to deserialize response.");
|
||||||
|
|
||||||
|
return altTextResponse.AltText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record AltTextResponse(string AltText);
|
||||||
|
|
||||||
|
class AltTextException(string message) : Exception(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace AltGen.Shared.Generate;
|
||||||
|
|
||||||
|
public record GenerateAltTextRequest(
|
||||||
|
string Provider,
|
||||||
|
string ProviderKey,
|
||||||
|
string FileName,
|
||||||
|
byte[] Image,
|
||||||
|
string ContentType
|
||||||
|
);
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace AltGen.Shared.Generate;
|
||||||
|
|
||||||
|
public interface IAltGenService
|
||||||
|
{
|
||||||
|
public Task<string> GenerateAltTextAsync(GenerateAltTextRequest req);
|
||||||
|
}
|
||||||
@@ -10,6 +10,11 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.3" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.3" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.3" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\AltGen.Shared\AltGen.Shared.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,24 +1,51 @@
|
|||||||
@inject ILogger<Home> Logger
|
@using AltGen.Shared.Generate
|
||||||
|
@inject ILogger<Home> Logger
|
||||||
|
@inject IAltGenService AltGenService
|
||||||
@page "/"
|
@page "/"
|
||||||
@rendermode InteractiveWebAssembly
|
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
|
||||||
|
|
||||||
<PageTitle>AltGen.Web</PageTitle>
|
<PageTitle>AltGen.Web</PageTitle>
|
||||||
|
|
||||||
<h1>AI Generated Alt Text</h1>
|
<h1>AI Generated Alt Text</h1>
|
||||||
|
|
||||||
<form method="post">
|
<form method="post">
|
||||||
<input type="text" @onchange="@(e => Logger.LogInformation("Text changed: {Value}", e.Value))" />
|
<div>
|
||||||
<InputFile OnChange="LoadFiles" multiple />
|
<label for="provider">Provider</label>
|
||||||
|
<input type="text" id="provider" name="provider" required @bind="_provider" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="providerKey">Provider Key</label>
|
||||||
|
<input type="password" id="providerKey" name="providerKey" required @bind="_providerKey" />
|
||||||
|
</div>
|
||||||
|
<InputFile OnChange="HandleFileChange" />
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private void LoadFiles(InputFileChangeEventArgs e)
|
private string? _provider;
|
||||||
{
|
private string? _providerKey;
|
||||||
var files = e.GetMultipleFiles(5);
|
|
||||||
|
|
||||||
foreach (var file in files)
|
private async Task HandleFileChange(InputFileChangeEventArgs e)
|
||||||
{
|
{
|
||||||
Logger.LogInformation("File loaded: {Name}, Size: {Size}", file.Name, file.Size);
|
var file = e.File;
|
||||||
|
|
||||||
|
if (_provider is null || _providerKey is null || file is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var fileBytes = new byte[file.Size];
|
||||||
|
using var stream = file.OpenReadStream();
|
||||||
|
await stream.ReadAsync(fileBytes, 0, (int)file.Size);
|
||||||
|
|
||||||
|
var altText = await AltGenService.GenerateAltTextAsync(new(
|
||||||
|
_provider,
|
||||||
|
_providerKey,
|
||||||
|
file.Name,
|
||||||
|
fileBytes,
|
||||||
|
file.ContentType
|
||||||
|
));
|
||||||
|
|
||||||
|
// TODO: Present on the screen to the user
|
||||||
|
Logger.LogInformation(altText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,10 @@
|
|||||||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
||||||
|
using AltGen.Shared.Generate;
|
||||||
|
|
||||||
var builder = WebAssemblyHostBuilder.CreateDefault(args);
|
var builder = WebAssemblyHostBuilder.CreateDefault(args);
|
||||||
|
|
||||||
|
// TODO: Read base url
|
||||||
|
// from configuration
|
||||||
|
builder.Services.AddHttpClient<IAltGenService, AltGenService>(c => c.BaseAddress = new("https://localhost:7297"));
|
||||||
|
|
||||||
await builder.Build().RunAsync();
|
await builder.Build().RunAsync();
|
||||||
|
|||||||
@@ -11,4 +11,8 @@
|
|||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.0.3" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.0.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\AltGen.Shared\AltGen.Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AltGen.Web", "AltGen.Web\Al
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AltGen.Web.Client", "AltGen.Web.Client\AltGen.Web.Client.csproj", "{DCE07E79-23A4-490E-A796-EA140D2040C1}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AltGen.Web.Client", "AltGen.Web.Client\AltGen.Web.Client.csproj", "{DCE07E79-23A4-490E-A796-EA140D2040C1}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AltGen.Shared", "AltGen.Shared\AltGen.Shared.csproj", "{68D4BC5D-A6FE-41CF-B744-1DB83CCFBC89}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -48,5 +50,9 @@ Global
|
|||||||
{DCE07E79-23A4-490E-A796-EA140D2040C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{DCE07E79-23A4-490E-A796-EA140D2040C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{DCE07E79-23A4-490E-A796-EA140D2040C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{DCE07E79-23A4-490E-A796-EA140D2040C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{DCE07E79-23A4-490E-A796-EA140D2040C1}.Release|Any CPU.Build.0 = Release|Any CPU
|
{DCE07E79-23A4-490E-A796-EA140D2040C1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{68D4BC5D-A6FE-41CF-B744-1DB83CCFBC89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{68D4BC5D-A6FE-41CF-B744-1DB83CCFBC89}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{68D4BC5D-A6FE-41CF-B744-1DB83CCFBC89}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{68D4BC5D-A6FE-41CF-B744-1DB83CCFBC89}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|||||||
Reference in New Issue
Block a user