feat(tracks): add ReleaseType and TrackNumber to track metadata model and CMS edit form
This commit is contained in:
@@ -7,6 +7,7 @@ using DeepDrftContent.FileDatabase.Models;
|
|||||||
using DeepDrftContent.Processors;
|
using DeepDrftContent.Processors;
|
||||||
using DeepDrftData;
|
using DeepDrftData;
|
||||||
using DeepDrftModels.DTOs;
|
using DeepDrftModels.DTOs;
|
||||||
|
using DeepDrftModels.Enums;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace DeepDrftAPI.Controllers;
|
namespace DeepDrftAPI.Controllers;
|
||||||
@@ -187,6 +188,8 @@ public class TrackController : ControllerBase
|
|||||||
[FromForm] string? releaseDate,
|
[FromForm] string? releaseDate,
|
||||||
[FromForm] string? originalFileName,
|
[FromForm] string? originalFileName,
|
||||||
[FromForm] long createdByUserId,
|
[FromForm] long createdByUserId,
|
||||||
|
[FromForm] string? releaseType,
|
||||||
|
[FromForm] int? trackNumber,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("UploadTrack called: trackName={TrackName}, artist={Artist}, fileName={FileName}, size={Size}",
|
_logger.LogInformation("UploadTrack called: trackName={TrackName}, artist={Artist}, fileName={FileName}, size={Size}",
|
||||||
@@ -222,6 +225,22 @@ public class TrackController : ControllerBase
|
|||||||
parsedReleaseDate = parsed;
|
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.
|
// 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.
|
// Path.GetTempFileName() yields .tmp, which fails that check — generate our own .wav path.
|
||||||
var tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N") + ".wav");
|
var tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N") + ".wav");
|
||||||
@@ -245,6 +264,8 @@ public class TrackController : ControllerBase
|
|||||||
parsedReleaseDate,
|
parsedReleaseDate,
|
||||||
createdByUserId,
|
createdByUserId,
|
||||||
string.IsNullOrWhiteSpace(originalFileName) ? null : originalFileName,
|
string.IsNullOrWhiteSpace(originalFileName) ? null : originalFileName,
|
||||||
|
parsedReleaseType,
|
||||||
|
resolvedTrackNumber,
|
||||||
cancellationToken);
|
cancellationToken);
|
||||||
|
|
||||||
if (!result.Success || result.Value is null)
|
if (!result.Success || result.Value is null)
|
||||||
@@ -339,6 +360,9 @@ public class TrackController : ControllerBase
|
|||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (request.TrackNumber is <= 0)
|
||||||
|
return BadRequest("trackNumber must be a positive integer when provided.");
|
||||||
|
|
||||||
var track = lookup.Value;
|
var track = lookup.Value;
|
||||||
track.TrackName = request.TrackName;
|
track.TrackName = request.TrackName;
|
||||||
track.Artist = request.Artist;
|
track.Artist = request.Artist;
|
||||||
@@ -350,6 +374,13 @@ public class TrackController : ControllerBase
|
|||||||
if (request.ImagePath is not null)
|
if (request.ImagePath is not null)
|
||||||
track.ImagePath = string.IsNullOrEmpty(request.ImagePath) ? null : request.ImagePath;
|
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);
|
var update = await _sqlTrackService.Update(track);
|
||||||
if (!update.Success)
|
if (!update.Success)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using DeepDrftModels.Enums;
|
||||||
|
|
||||||
namespace DeepDrftAPI.Models;
|
namespace DeepDrftAPI.Models;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -15,4 +17,6 @@ public record UpdateTrackMetadataRequest(
|
|||||||
string? Album,
|
string? Album,
|
||||||
string? Genre,
|
string? Genre,
|
||||||
DateOnly? ReleaseDate,
|
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 DeepDrftContent.Processors;
|
||||||
using DeepDrftData;
|
using DeepDrftData;
|
||||||
using DeepDrftModels.DTOs;
|
using DeepDrftModels.DTOs;
|
||||||
|
using DeepDrftModels.Enums;
|
||||||
using NetBlocks.Models;
|
using NetBlocks.Models;
|
||||||
using FileDb = DeepDrftContent.FileDatabase.Services.FileDatabase;
|
using FileDb = DeepDrftContent.FileDatabase.Services.FileDatabase;
|
||||||
|
|
||||||
@@ -50,6 +51,8 @@ public class UnifiedTrackService
|
|||||||
DateOnly? releaseDate,
|
DateOnly? releaseDate,
|
||||||
long createdByUserId,
|
long createdByUserId,
|
||||||
string? originalFileName,
|
string? originalFileName,
|
||||||
|
ReleaseType releaseType,
|
||||||
|
int trackNumber,
|
||||||
CancellationToken ct)
|
CancellationToken ct)
|
||||||
{
|
{
|
||||||
var unpersisted = await _contentTrackContentService.AddTrackFromWavAsync(
|
var unpersisted = await _contentTrackContentService.AddTrackFromWavAsync(
|
||||||
@@ -62,6 +65,8 @@ public class UnifiedTrackService
|
|||||||
}
|
}
|
||||||
|
|
||||||
unpersisted.CreatedByUserId = createdByUserId;
|
unpersisted.CreatedByUserId = createdByUserId;
|
||||||
|
unpersisted.ReleaseType = releaseType;
|
||||||
|
unpersisted.TrackNumber = trackNumber;
|
||||||
|
|
||||||
var saveResult = await _sqlTrackService.Create(TrackConverter.Convert(unpersisted));
|
var saveResult = await _sqlTrackService.Create(TrackConverter.Convert(unpersisted));
|
||||||
if (!saveResult.Success || saveResult.Value is null)
|
if (!saveResult.Success || saveResult.Value is null)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Data.Data.Configurations;
|
using Data.Data.Configurations;
|
||||||
using DeepDrftModels.Entities;
|
using DeepDrftModels.Entities;
|
||||||
|
using DeepDrftModels.Enums;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
@@ -57,6 +58,18 @@ public class TrackConfiguration : BaseEntityConfiguration<TrackEntity>
|
|||||||
.HasMaxLength(500)
|
.HasMaxLength(500)
|
||||||
.HasColumnName("original_file_name");
|
.HasColumnName("original_file_name");
|
||||||
|
|
||||||
|
builder.Property(e => e.ReleaseType)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConversion<string>() // Store as readable string, not int ordinal
|
||||||
|
.HasMaxLength(20)
|
||||||
|
.HasColumnName("release_type")
|
||||||
|
.HasDefaultValue(ReleaseType.Single);
|
||||||
|
|
||||||
|
builder.Property(e => e.TrackNumber)
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnName("track_number")
|
||||||
|
.HasDefaultValue(1);
|
||||||
|
|
||||||
// Names the is_deleted index explicitly. BaseEntityConfiguration.Configure already
|
// Names the is_deleted index explicitly. BaseEntityConfiguration.Configure already
|
||||||
// calls HasIndex(e => e.IsDeleted); this adds HasDatabaseName so EF always uses
|
// calls HasIndex(e => e.IsDeleted); this adds HasDatabaseName so EF always uses
|
||||||
// "IX_track_is_deleted" regardless of auto-naming conventions.
|
// "IX_track_is_deleted" regardless of auto-naming conventions.
|
||||||
|
|||||||
+121
@@ -0,0 +1,121 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using DeepDrftData.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace DeepDrftData.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(DeepDrftContext))]
|
||||||
|
[Migration("20260611005700_AddReleaseTypeAndTrackNumber")]
|
||||||
|
partial class AddReleaseTypeAndTrackNumber
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "10.0.7")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("DeepDrftModels.Entities.TrackEntity", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Album")
|
||||||
|
.HasMaxLength(200)
|
||||||
|
.HasColumnType("character varying(200)")
|
||||||
|
.HasColumnName("album");
|
||||||
|
|
||||||
|
b.Property<string>("Artist")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(200)
|
||||||
|
.HasColumnType("character varying(200)")
|
||||||
|
.HasColumnName("artist");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("created_at");
|
||||||
|
|
||||||
|
b.Property<long?>("CreatedByUserId")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("created_by_user_id");
|
||||||
|
|
||||||
|
b.Property<string>("EntryKey")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("entry_key");
|
||||||
|
|
||||||
|
b.Property<string>("Genre")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("character varying(100)")
|
||||||
|
.HasColumnName("genre");
|
||||||
|
|
||||||
|
b.Property<string>("ImagePath")
|
||||||
|
.HasMaxLength(500)
|
||||||
|
.HasColumnType("character varying(500)")
|
||||||
|
.HasColumnName("image_path");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDeleted")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasDefaultValue(false)
|
||||||
|
.HasColumnName("is_deleted");
|
||||||
|
|
||||||
|
b.Property<string>("OriginalFileName")
|
||||||
|
.HasMaxLength(500)
|
||||||
|
.HasColumnType("character varying(500)")
|
||||||
|
.HasColumnName("original_file_name");
|
||||||
|
|
||||||
|
b.Property<DateOnly?>("ReleaseDate")
|
||||||
|
.HasColumnType("date")
|
||||||
|
.HasColumnName("release_date");
|
||||||
|
|
||||||
|
b.Property<string>("ReleaseType")
|
||||||
|
.IsRequired()
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasMaxLength(20)
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasDefaultValue("Single")
|
||||||
|
.HasColumnName("release_type");
|
||||||
|
|
||||||
|
b.Property<string>("TrackName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(200)
|
||||||
|
.HasColumnType("character varying(200)")
|
||||||
|
.HasColumnName("track_name");
|
||||||
|
|
||||||
|
b.Property<int>("TrackNumber")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasDefaultValue(1)
|
||||||
|
.HasColumnName("track_number");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("updated_at");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("IsDeleted")
|
||||||
|
.HasDatabaseName("IX_track_is_deleted");
|
||||||
|
|
||||||
|
b.ToTable("track", (string)null);
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace DeepDrftData.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddReleaseTypeAndTrackNumber : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "release_type",
|
||||||
|
table: "track",
|
||||||
|
type: "character varying(20)",
|
||||||
|
maxLength: 20,
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: "Single");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "track_number",
|
||||||
|
table: "track",
|
||||||
|
type: "integer",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "release_type",
|
||||||
|
table: "track");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "track_number",
|
||||||
|
table: "track");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -81,12 +81,26 @@ namespace DeepDrftData.Migrations
|
|||||||
.HasColumnType("date")
|
.HasColumnType("date")
|
||||||
.HasColumnName("release_date");
|
.HasColumnName("release_date");
|
||||||
|
|
||||||
|
b.Property<string>("ReleaseType")
|
||||||
|
.IsRequired()
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasMaxLength(20)
|
||||||
|
.HasColumnType("character varying(20)")
|
||||||
|
.HasDefaultValue("Single")
|
||||||
|
.HasColumnName("release_type");
|
||||||
|
|
||||||
b.Property<string>("TrackName")
|
b.Property<string>("TrackName")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasMaxLength(200)
|
.HasMaxLength(200)
|
||||||
.HasColumnType("character varying(200)")
|
.HasColumnType("character varying(200)")
|
||||||
.HasColumnName("track_name");
|
.HasColumnName("track_name");
|
||||||
|
|
||||||
|
b.Property<int>("TrackNumber")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasDefaultValue(1)
|
||||||
|
.HasColumnName("track_number");
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
b.Property<DateTime>("UpdatedAt")
|
||||||
.HasColumnType("timestamp with time zone")
|
.HasColumnType("timestamp with time zone")
|
||||||
.HasColumnName("updated_at");
|
.HasColumnName("updated_at");
|
||||||
|
|||||||
@@ -25,7 +25,9 @@ public class TrackConverter : IEntityToModelConverter<TrackEntity, TrackDto>
|
|||||||
ReleaseDate = entity.ReleaseDate,
|
ReleaseDate = entity.ReleaseDate,
|
||||||
ImagePath = entity.ImagePath,
|
ImagePath = entity.ImagePath,
|
||||||
CreatedByUserId = entity.CreatedByUserId,
|
CreatedByUserId = entity.CreatedByUserId,
|
||||||
OriginalFileName = entity.OriginalFileName
|
OriginalFileName = entity.OriginalFileName,
|
||||||
|
ReleaseType = entity.ReleaseType,
|
||||||
|
TrackNumber = entity.TrackNumber
|
||||||
};
|
};
|
||||||
|
|
||||||
public static TrackEntity Convert(TrackDto model) => new()
|
public static TrackEntity Convert(TrackDto model) => new()
|
||||||
@@ -41,6 +43,8 @@ public class TrackConverter : IEntityToModelConverter<TrackEntity, TrackDto>
|
|||||||
ReleaseDate = model.ReleaseDate,
|
ReleaseDate = model.ReleaseDate,
|
||||||
ImagePath = model.ImagePath,
|
ImagePath = model.ImagePath,
|
||||||
CreatedByUserId = model.CreatedByUserId,
|
CreatedByUserId = model.CreatedByUserId,
|
||||||
OriginalFileName = model.OriginalFileName
|
OriginalFileName = model.OriginalFileName,
|
||||||
|
ReleaseType = model.ReleaseType,
|
||||||
|
TrackNumber = model.TrackNumber
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
@page "/tracks/{Id:long}"
|
@page "/tracks/{Id:long}"
|
||||||
@using DeepDrftManager.Services
|
@using DeepDrftManager.Services
|
||||||
|
@using DeepDrftModels.Enums
|
||||||
@using Microsoft.AspNetCore.Components.Forms
|
@using Microsoft.AspNetCore.Components.Forms
|
||||||
@attribute [Authorize]
|
@attribute [Authorize]
|
||||||
@inject ICmsTrackService CmsTrackService
|
@inject ICmsTrackService CmsTrackService
|
||||||
@@ -62,6 +63,20 @@
|
|||||||
Label="Genre"
|
Label="Genre"
|
||||||
Variant="Variant.Outlined" />
|
Variant="Variant.Outlined" />
|
||||||
|
|
||||||
|
<MudSelect @bind-Value="_form.ReleaseType"
|
||||||
|
Label="Release Type"
|
||||||
|
Variant="Variant.Outlined">
|
||||||
|
@foreach (var releaseType in Enum.GetValues<ReleaseType>())
|
||||||
|
{
|
||||||
|
<MudSelectItem Value="releaseType">@releaseType</MudSelectItem>
|
||||||
|
}
|
||||||
|
</MudSelect>
|
||||||
|
|
||||||
|
<MudNumericField @bind-Value="_form.TrackNumber"
|
||||||
|
Label="Track Number"
|
||||||
|
Min="1"
|
||||||
|
Variant="Variant.Outlined" />
|
||||||
|
|
||||||
<MudField Label="Cover Art" Variant="Variant.Outlined" InnerPadding="false">
|
<MudField Label="Cover Art" Variant="Variant.Outlined" InnerPadding="false">
|
||||||
<MudStack Spacing="3">
|
<MudStack Spacing="3">
|
||||||
@if (ImagePreviewUrl is { } previewUrl)
|
@if (ImagePreviewUrl is { } previewUrl)
|
||||||
@@ -207,7 +222,9 @@
|
|||||||
string.IsNullOrWhiteSpace(_form.Album) ? null : _form.Album,
|
string.IsNullOrWhiteSpace(_form.Album) ? null : _form.Album,
|
||||||
string.IsNullOrWhiteSpace(_form.Genre) ? null : _form.Genre,
|
string.IsNullOrWhiteSpace(_form.Genre) ? null : _form.Genre,
|
||||||
releaseDate,
|
releaseDate,
|
||||||
string.IsNullOrEmpty(_form.ImagePath) ? "" : _form.ImagePath);
|
string.IsNullOrEmpty(_form.ImagePath) ? "" : _form.ImagePath,
|
||||||
|
_form.ReleaseType,
|
||||||
|
_form.TrackNumber);
|
||||||
if (updated.Success)
|
if (updated.Success)
|
||||||
{
|
{
|
||||||
Snackbar.Add("Track updated.", Severity.Success);
|
Snackbar.Add("Track updated.", Severity.Success);
|
||||||
@@ -287,6 +304,8 @@
|
|||||||
public string? Genre { get; set; }
|
public string? Genre { get; set; }
|
||||||
public string? ImagePath { get; set; }
|
public string? ImagePath { get; set; }
|
||||||
public DateTime? ReleaseDate { get; set; }
|
public DateTime? ReleaseDate { get; set; }
|
||||||
|
public ReleaseType ReleaseType { get; set; } = ReleaseType.Single;
|
||||||
|
public int TrackNumber { get; set; } = 1;
|
||||||
|
|
||||||
public static TrackEditForm From(TrackDto track) => new()
|
public static TrackEditForm From(TrackDto track) => new()
|
||||||
{
|
{
|
||||||
@@ -297,7 +316,9 @@
|
|||||||
ImagePath = track.ImagePath,
|
ImagePath = track.ImagePath,
|
||||||
ReleaseDate = track.ReleaseDate is { } d
|
ReleaseDate = track.ReleaseDate is { } d
|
||||||
? d.ToDateTime(TimeOnly.MinValue)
|
? d.ToDateTime(TimeOnly.MinValue)
|
||||||
: null
|
: null,
|
||||||
|
ReleaseType = track.ReleaseType,
|
||||||
|
TrackNumber = track.TrackNumber
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
@page "/tracks/new"
|
@page "/tracks/new"
|
||||||
@using System.Security.Claims
|
@using System.Security.Claims
|
||||||
@using DeepDrftManager.Services
|
@using DeepDrftManager.Services
|
||||||
|
@using DeepDrftModels.Enums
|
||||||
@attribute [Authorize]
|
@attribute [Authorize]
|
||||||
|
|
||||||
@inject ICmsTrackService CmsTrackService
|
@inject ICmsTrackService CmsTrackService
|
||||||
@@ -202,7 +203,9 @@
|
|||||||
string.IsNullOrWhiteSpace(_genre) ? null : _genre,
|
string.IsNullOrWhiteSpace(_genre) ? null : _genre,
|
||||||
string.IsNullOrWhiteSpace(_releaseDate) ? null : _releaseDate,
|
string.IsNullOrWhiteSpace(_releaseDate) ? null : _releaseDate,
|
||||||
_selectedFile.Name,
|
_selectedFile.Name,
|
||||||
createdByUserId);
|
createdByUserId,
|
||||||
|
releaseType: ReleaseType.Single,
|
||||||
|
trackNumber: 1);
|
||||||
|
|
||||||
if (result.Success)
|
if (result.Success)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using System.Net;
|
|||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Net.Http.Json;
|
using System.Net.Http.Json;
|
||||||
using DeepDrftModels.DTOs;
|
using DeepDrftModels.DTOs;
|
||||||
|
using DeepDrftModels.Enums;
|
||||||
using Models.Common;
|
using Models.Common;
|
||||||
using NetBlocks.Models;
|
using NetBlocks.Models;
|
||||||
|
|
||||||
@@ -41,6 +42,8 @@ public class CmsTrackService : ICmsTrackService
|
|||||||
string? releaseDate,
|
string? releaseDate,
|
||||||
string? originalFileName,
|
string? originalFileName,
|
||||||
long createdByUserId,
|
long createdByUserId,
|
||||||
|
ReleaseType releaseType,
|
||||||
|
int trackNumber,
|
||||||
CancellationToken ct = default)
|
CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
// Rebuild the multipart container so the boundary is owned by HttpClient and the
|
// Rebuild the multipart container so the boundary is owned by HttpClient and the
|
||||||
@@ -58,6 +61,8 @@ public class CmsTrackService : ICmsTrackService
|
|||||||
// Explicit field — decouples the admin-visible display name from the WAV part's content-disposition filename.
|
// Explicit field — decouples the admin-visible display name from the WAV part's content-disposition filename.
|
||||||
if (!string.IsNullOrWhiteSpace(originalFileName)) multipart.Add(new StringContent(originalFileName), "originalFileName");
|
if (!string.IsNullOrWhiteSpace(originalFileName)) multipart.Add(new StringContent(originalFileName), "originalFileName");
|
||||||
multipart.Add(new StringContent(createdByUserId.ToString()), "createdByUserId");
|
multipart.Add(new StringContent(createdByUserId.ToString()), "createdByUserId");
|
||||||
|
multipart.Add(new StringContent(releaseType.ToString()), "releaseType");
|
||||||
|
multipart.Add(new StringContent(trackNumber.ToString()), "trackNumber");
|
||||||
|
|
||||||
var client = _httpClientFactory.CreateClient(ContentCmsClientName);
|
var client = _httpClientFactory.CreateClient(ContentCmsClientName);
|
||||||
using var request = new HttpRequestMessage(HttpMethod.Post, UploadPath) { Content = multipart };
|
using var request = new HttpRequestMessage(HttpMethod.Post, UploadPath) { Content = multipart };
|
||||||
@@ -322,6 +327,8 @@ public class CmsTrackService : ICmsTrackService
|
|||||||
long id, string trackName, string artist,
|
long id, string trackName, string artist,
|
||||||
string? album, string? genre, DateOnly? releaseDate,
|
string? album, string? genre, DateOnly? releaseDate,
|
||||||
string? imagePath = null,
|
string? imagePath = null,
|
||||||
|
ReleaseType? releaseType = null,
|
||||||
|
int? trackNumber = null,
|
||||||
CancellationToken ct = default)
|
CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
var client = _httpClientFactory.CreateClient(ContentCmsClientName);
|
var client = _httpClientFactory.CreateClient(ContentCmsClientName);
|
||||||
@@ -333,6 +340,8 @@ public class CmsTrackService : ICmsTrackService
|
|||||||
genre,
|
genre,
|
||||||
releaseDate,
|
releaseDate,
|
||||||
imagePath,
|
imagePath,
|
||||||
|
releaseType = releaseType?.ToString(),
|
||||||
|
trackNumber,
|
||||||
};
|
};
|
||||||
|
|
||||||
HttpResponseMessage response;
|
HttpResponseMessage response;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using DeepDrftModels.DTOs;
|
using DeepDrftModels.DTOs;
|
||||||
|
using DeepDrftModels.Enums;
|
||||||
using Models.Common;
|
using Models.Common;
|
||||||
using NetBlocks.Models;
|
using NetBlocks.Models;
|
||||||
|
|
||||||
@@ -29,6 +30,8 @@ public interface ICmsTrackService
|
|||||||
string? releaseDate,
|
string? releaseDate,
|
||||||
string? originalFileName,
|
string? originalFileName,
|
||||||
long createdByUserId,
|
long createdByUserId,
|
||||||
|
ReleaseType releaseType,
|
||||||
|
int trackNumber,
|
||||||
CancellationToken ct = default);
|
CancellationToken ct = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -69,6 +72,8 @@ public interface ICmsTrackService
|
|||||||
long id, string trackName, string artist,
|
long id, string trackName, string artist,
|
||||||
string? album, string? genre, DateOnly? releaseDate,
|
string? album, string? genre, DateOnly? releaseDate,
|
||||||
string? imagePath = null,
|
string? imagePath = null,
|
||||||
|
ReleaseType? releaseType = null,
|
||||||
|
int? trackNumber = null,
|
||||||
CancellationToken ct = default);
|
CancellationToken ct = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using DeepDrftModels.Enums;
|
||||||
using Models.Models;
|
using Models.Models;
|
||||||
|
|
||||||
namespace DeepDrftModels.DTOs;
|
namespace DeepDrftModels.DTOs;
|
||||||
@@ -19,4 +20,6 @@ public class TrackDto : BaseModel
|
|||||||
public string? ImagePath { get; set; }
|
public string? ImagePath { get; set; }
|
||||||
public long? CreatedByUserId { get; set; }
|
public long? CreatedByUserId { get; set; }
|
||||||
public string? OriginalFileName { get; set; }
|
public string? OriginalFileName { get; set; }
|
||||||
|
public ReleaseType ReleaseType { get; set; } = ReleaseType.Single;
|
||||||
|
public int TrackNumber { get; set; } = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using DeepDrftModels.Enums;
|
||||||
using Models.Entities;
|
using Models.Entities;
|
||||||
|
|
||||||
namespace DeepDrftModels.Entities;
|
namespace DeepDrftModels.Entities;
|
||||||
@@ -16,4 +17,6 @@ public class TrackEntity : BaseEntity, IEntity
|
|||||||
public string? ImagePath { get; set; }
|
public string? ImagePath { get; set; }
|
||||||
public long? CreatedByUserId { get; set; }
|
public long? CreatedByUserId { get; set; }
|
||||||
public string? OriginalFileName { get; set; }
|
public string? OriginalFileName { get; set; }
|
||||||
|
public ReleaseType ReleaseType { get; set; } = ReleaseType.Single;
|
||||||
|
public int TrackNumber { get; set; } = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace DeepDrftModels.Enums;
|
||||||
|
|
||||||
|
/// <summary>The commercial release format of a track's parent release.</summary>
|
||||||
|
public enum ReleaseType
|
||||||
|
{
|
||||||
|
Single,
|
||||||
|
EP,
|
||||||
|
Album
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user