Refactor bumper template background management: rename background upload endpoint to reflect new functionality, update related command and handler to use image ID instead of extension, and adjust data models to support image references. Remove obsolete background handling code and enhance UI components for improved image selection and display.
This commit is contained in:
@@ -75,7 +75,7 @@ public static class ChannelEndpoints
|
||||
.MapDelete("/{id:guid}/bumper/templates/{templateId:guid}/audio", ClearTemplateAudio)
|
||||
.Produces(StatusCodes.Status204NoContent);
|
||||
admin
|
||||
.MapPut("/{id:guid}/bumper/templates/{templateId:guid}/background", UploadTemplateBackground)
|
||||
.MapPut("/{id:guid}/bumper/templates/{templateId:guid}/background", SetTemplateBackground)
|
||||
.Produces(StatusCodes.Status204NoContent);
|
||||
admin
|
||||
.MapDelete("/{id:guid}/bumper/templates/{templateId:guid}/background", ClearTemplateBackground)
|
||||
@@ -333,27 +333,18 @@ public static class ChannelEndpoints
|
||||
return result.ToHttpResult();
|
||||
}
|
||||
|
||||
private static async Task<IResult> UploadTemplateBackground(
|
||||
private static async Task<IResult> SetTemplateBackground(
|
||||
Guid id,
|
||||
Guid templateId,
|
||||
string fileName,
|
||||
HttpRequest request,
|
||||
IBumperTemplateStorage storage,
|
||||
SetBumperTemplateBackgroundBody body,
|
||||
ISender sender,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
if (ResolveBumperExtension(fileName, request, BumperFiles.BackgroundExtensions) is not { } ext)
|
||||
return ChannelErrors.InvalidBumperFile.ToProblem();
|
||||
|
||||
await storage.SaveBackgroundAsync(templateId, ext, request.Body, cancellationToken);
|
||||
|
||||
var result = await sender.Send(
|
||||
new SetBumperTemplateBackgroundCommand(id, templateId, ext),
|
||||
new SetBumperTemplateBackgroundCommand(id, templateId, body.ImageId),
|
||||
cancellationToken
|
||||
);
|
||||
if (!result.IsSuccess)
|
||||
storage.DeleteBackground(templateId);
|
||||
return result.ToHttpResult();
|
||||
}
|
||||
|
||||
@@ -539,6 +530,8 @@ public sealed record AddChannelAdBody(Guid MediaAssetId);
|
||||
|
||||
public sealed record AddBumperTemplateBody(string Name);
|
||||
|
||||
public sealed record SetBumperTemplateBackgroundBody(Guid ImageId);
|
||||
|
||||
public sealed record UpdateBumperTemplateBody(
|
||||
string Name,
|
||||
string BackgroundColor,
|
||||
@@ -547,24 +540,11 @@ public sealed record UpdateBumperTemplateBody(
|
||||
string TextColor
|
||||
);
|
||||
|
||||
/// <summary>Ограничения на загружаемые файлы блока заставки (звук/фон-картинка).</summary>
|
||||
/// <summary>Ограничения на загружаемый звук блока заставки (фон-картинка — через общий реестр).</summary>
|
||||
internal static class BumperFiles
|
||||
{
|
||||
public const long MaxBytes = 200L * 1024 * 1024; // 200 МБ
|
||||
|
||||
// Фон блока — только картинка (видео-фоны в новой модели не поддерживаются).
|
||||
public static readonly IReadOnlySet<string> BackgroundExtensions = new HashSet<string>(
|
||||
StringComparer.OrdinalIgnoreCase
|
||||
)
|
||||
{
|
||||
".jpg",
|
||||
".jpeg",
|
||||
".png",
|
||||
".webp",
|
||||
".bmp",
|
||||
".gif",
|
||||
};
|
||||
|
||||
public static readonly IReadOnlySet<string> AudioExtensions = new HashSet<string>(
|
||||
StringComparer.OrdinalIgnoreCase
|
||||
)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using LiteCqrs;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using TeleWave.Api.Common;
|
||||
using TeleWave.Application.Common.Interfaces;
|
||||
using TeleWave.Application.Images.DeleteImage;
|
||||
@@ -48,12 +47,7 @@ public static class MetadataEndpoints
|
||||
.Produces(StatusCodes.Status204NoContent);
|
||||
admin.MapPost("/shows/{showId:guid}/refresh-episodes", RefreshEpisodes).Produces<int>();
|
||||
|
||||
// Кадры серий отдаём публично (просто картинки, id не угадать) — чтобы работал <img src>.
|
||||
// Постеры шоу теперь в общем реестре и отдаются по /api/images/{id}.
|
||||
app.MapGet("/api/metadata/episodes/{episodeId:guid}/still", ServeStill)
|
||||
.WithTags("Metadata")
|
||||
.Produces(StatusCodes.Status200OK);
|
||||
|
||||
// Постеры шоу и кадры серий теперь в общем реестре и отдаются по /api/images/{id}.
|
||||
return app;
|
||||
}
|
||||
|
||||
@@ -181,37 +175,6 @@ public static class MetadataEndpoints
|
||||
);
|
||||
return result.ToHttpResult();
|
||||
}
|
||||
|
||||
private static async Task<IResult> ServeStill(
|
||||
Guid episodeId,
|
||||
IAppDbContext dbContext,
|
||||
IMetadataImageStore imageStore,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
var path = await dbContext.Shows.AsNoTracking()
|
||||
.SelectMany(s => s.Episodes)
|
||||
.Where(e => e.Id == episodeId)
|
||||
.Select(e => e.StillPath)
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
return ServeImage(path, imageStore);
|
||||
}
|
||||
|
||||
private static IResult ServeImage(string? relativePath, IMetadataImageStore imageStore)
|
||||
{
|
||||
if (string.IsNullOrEmpty(relativePath))
|
||||
return Results.NotFound();
|
||||
var abs = imageStore.ResolveAbsolutePath(relativePath);
|
||||
return abs is null ? Results.NotFound() : Results.File(abs, ContentTypeFor(Path.GetExtension(abs)));
|
||||
}
|
||||
|
||||
private static string ContentTypeFor(string extension) =>
|
||||
extension.ToLowerInvariant() switch
|
||||
{
|
||||
".png" => "image/png",
|
||||
".webp" => "image/webp",
|
||||
_ => "image/jpeg",
|
||||
};
|
||||
}
|
||||
|
||||
public sealed record ApplyMetadataBody(string Provider, string ExternalId);
|
||||
|
||||
Reference in New Issue
Block a user