feat(tracks): add ReleaseType and TrackNumber to track metadata model and CMS edit form

This commit is contained in:
daniel-c-harvey
2026-06-10 21:36:00 -04:00
parent f8186fb7c7
commit d47a5e00af
15 changed files with 292 additions and 6 deletions
@@ -7,6 +7,7 @@ using DeepDrftContent.FileDatabase.Models;
using DeepDrftContent.Processors;
using DeepDrftData;
using DeepDrftModels.DTOs;
using DeepDrftModels.Enums;
using Microsoft.AspNetCore.Mvc;
namespace DeepDrftAPI.Controllers;
@@ -187,6 +188,8 @@ public class TrackController : ControllerBase
[FromForm] string? releaseDate,
[FromForm] string? originalFileName,
[FromForm] long createdByUserId,
[FromForm] string? releaseType,
[FromForm] int? trackNumber,
CancellationToken cancellationToken)
{
_logger.LogInformation("UploadTrack called: trackName={TrackName}, artist={Artist}, fileName={FileName}, size={Size}",
@@ -222,6 +225,22 @@ public class TrackController : ControllerBase
parsedReleaseDate = parsed;
}
// Default to Single for null/unparseable release type; default track number to a valid 1-based value.
ReleaseType parsedReleaseType;
if (!string.IsNullOrWhiteSpace(releaseType)
&& Enum.TryParse<ReleaseType>(releaseType, ignoreCase: true, out var rt)
&& Enum.IsDefined(rt))
{
parsedReleaseType = rt;
}
else
{
parsedReleaseType = ReleaseType.Single;
if (!string.IsNullOrWhiteSpace(releaseType))
_logger.LogWarning("UploadTrack: unrecognised releaseType value '{Value}', defaulting to Single", releaseType);
}
var resolvedTrackNumber = trackNumber is > 0 ? trackNumber.Value : 1;
// AudioProcessor.ProcessWavFileAsync requires a path ending in .wav and reads from disk.
// Path.GetTempFileName() yields .tmp, which fails that check — generate our own .wav path.
var tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N") + ".wav");
@@ -245,6 +264,8 @@ public class TrackController : ControllerBase
parsedReleaseDate,
createdByUserId,
string.IsNullOrWhiteSpace(originalFileName) ? null : originalFileName,
parsedReleaseType,
resolvedTrackNumber,
cancellationToken);
if (!result.Success || result.Value is null)
@@ -339,6 +360,9 @@ public class TrackController : ControllerBase
return NotFound();
}
if (request.TrackNumber is <= 0)
return BadRequest("trackNumber must be a positive integer when provided.");
var track = lookup.Value;
track.TrackName = request.TrackName;
track.Artist = request.Artist;
@@ -350,6 +374,13 @@ public class TrackController : ControllerBase
if (request.ImagePath is not null)
track.ImagePath = string.IsNullOrEmpty(request.ImagePath) ? null : request.ImagePath;
// ReleaseType / TrackNumber are non-null on the entity; null in the request means "no change".
if (request.ReleaseType is not null)
track.ReleaseType = request.ReleaseType.Value;
if (request.TrackNumber is > 0)
track.TrackNumber = request.TrackNumber.Value;
var update = await _sqlTrackService.Update(track);
if (!update.Success)
{
@@ -1,3 +1,5 @@
using DeepDrftModels.Enums;
namespace DeepDrftAPI.Models;
/// <summary>
@@ -15,4 +17,6 @@ public record UpdateTrackMetadataRequest(
string? Album,
string? Genre,
DateOnly? ReleaseDate,
string? ImagePath = null);
string? ImagePath = null,
ReleaseType? ReleaseType = null,
int? TrackNumber = null);
@@ -3,6 +3,7 @@ using DeepDrftContent.Constants;
using DeepDrftContent.Processors;
using DeepDrftData;
using DeepDrftModels.DTOs;
using DeepDrftModels.Enums;
using NetBlocks.Models;
using FileDb = DeepDrftContent.FileDatabase.Services.FileDatabase;
@@ -50,6 +51,8 @@ public class UnifiedTrackService
DateOnly? releaseDate,
long createdByUserId,
string? originalFileName,
ReleaseType releaseType,
int trackNumber,
CancellationToken ct)
{
var unpersisted = await _contentTrackContentService.AddTrackFromWavAsync(
@@ -62,6 +65,8 @@ public class UnifiedTrackService
}
unpersisted.CreatedByUserId = createdByUserId;
unpersisted.ReleaseType = releaseType;
unpersisted.TrackNumber = trackNumber;
var saveResult = await _sqlTrackService.Create(TrackConverter.Convert(unpersisted));
if (!saveResult.Success || saveResult.Value is null)