diff --git a/DeepDrftAPI/Controllers/TrackController.cs b/DeepDrftAPI/Controllers/TrackController.cs
index 6591dc9..83ad7ec 100644
--- a/DeepDrftAPI/Controllers/TrackController.cs
+++ b/DeepDrftAPI/Controllers/TrackController.cs
@@ -124,11 +124,12 @@ public class TrackController : ControllerBase
[FromForm] string? album,
[FromForm] string? genre,
[FromForm] string? releaseDate,
+ [FromForm] string? originalFileName,
[FromForm] long createdByUserId,
CancellationToken cancellationToken)
{
- _logger.LogInformation("UploadTrack called: trackName={TrackName}, artist={Artist}, size={Size}",
- trackName, artist, wav?.Length);
+ _logger.LogInformation("UploadTrack called: trackName={TrackName}, artist={Artist}, fileName={FileName}, size={Size}",
+ trackName, artist, originalFileName, wav?.Length);
if (wav is null || wav.Length == 0)
{
@@ -182,6 +183,7 @@ public class TrackController : ControllerBase
string.IsNullOrWhiteSpace(genre) ? null : genre,
parsedReleaseDate,
createdByUserId,
+ string.IsNullOrWhiteSpace(originalFileName) ? null : originalFileName,
cancellationToken);
if (!result.Success || result.Value is null)
diff --git a/DeepDrftAPI/Services/UnifiedTrackService.cs b/DeepDrftAPI/Services/UnifiedTrackService.cs
index 6963100..796105c 100644
--- a/DeepDrftAPI/Services/UnifiedTrackService.cs
+++ b/DeepDrftAPI/Services/UnifiedTrackService.cs
@@ -49,10 +49,11 @@ public class UnifiedTrackService
string? genre,
DateOnly? releaseDate,
long createdByUserId,
+ string? originalFileName,
CancellationToken ct)
{
var unpersisted = await _contentTrackContentService.AddTrackFromWavAsync(
- tempFilePath, trackName, artist, album, genre, releaseDate);
+ tempFilePath, trackName, artist, album, genre, releaseDate, originalFileName: originalFileName);
if (unpersisted is null)
{
diff --git a/DeepDrftContent/TrackContentService.cs b/DeepDrftContent/TrackContentService.cs
index 7a4f8a3..6eaf7a2 100644
--- a/DeepDrftContent/TrackContentService.cs
+++ b/DeepDrftContent/TrackContentService.cs
@@ -29,6 +29,7 @@ public class TrackContentService
/// Optional album name
/// Optional genre
/// Optional release date
+ /// Optional original browser filename captured at upload time
/// The track entity with generated ID and media path
public async Task AddTrackFromWavAsync(
string wavFilePath,
@@ -36,7 +37,8 @@ public class TrackContentService
string artist,
string? album = null,
string? genre = null,
- DateOnly? releaseDate = null)
+ DateOnly? releaseDate = null,
+ string? originalFileName = null)
{
try
{
@@ -71,7 +73,8 @@ public class TrackContentService
Artist = artist,
Album = album,
Genre = genre,
- ReleaseDate = releaseDate
+ ReleaseDate = releaseDate,
+ OriginalFileName = originalFileName
};
return trackEntity;
diff --git a/DeepDrftData/Data/Configurations/TrackConfiguration.cs b/DeepDrftData/Data/Configurations/TrackConfiguration.cs
index 1075da7..128639d 100644
--- a/DeepDrftData/Data/Configurations/TrackConfiguration.cs
+++ b/DeepDrftData/Data/Configurations/TrackConfiguration.cs
@@ -53,6 +53,10 @@ public class TrackConfiguration : BaseEntityConfiguration
builder.Property(e => e.CreatedByUserId)
.HasColumnName("created_by_user_id");
+ builder.Property(e => e.OriginalFileName)
+ .HasMaxLength(500)
+ .HasColumnName("original_file_name");
+
// Names the is_deleted index explicitly. BaseEntityConfiguration.Configure already
// calls HasIndex(e => e.IsDeleted); this adds HasDatabaseName so EF always uses
// "IX_track_is_deleted" regardless of auto-naming conventions.
diff --git a/DeepDrftData/Migrations/20260607124422_AddOriginalFileName.Designer.cs b/DeepDrftData/Migrations/20260607124422_AddOriginalFileName.Designer.cs
new file mode 100644
index 0000000..cd2d5f4
--- /dev/null
+++ b/DeepDrftData/Migrations/20260607124422_AddOriginalFileName.Designer.cs
@@ -0,0 +1,107 @@
+//
+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("20260607124422_AddOriginalFileName")]
+ partial class AddOriginalFileName
+ {
+ ///
+ 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("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Album")
+ .HasMaxLength(200)
+ .HasColumnType("character varying(200)")
+ .HasColumnName("album");
+
+ b.Property("Artist")
+ .IsRequired()
+ .HasMaxLength(200)
+ .HasColumnType("character varying(200)")
+ .HasColumnName("artist");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("created_at");
+
+ b.Property("CreatedByUserId")
+ .HasColumnType("bigint")
+ .HasColumnName("created_by_user_id");
+
+ b.Property("EntryKey")
+ .IsRequired()
+ .HasMaxLength(100)
+ .HasColumnType("character varying(100)")
+ .HasColumnName("entry_key");
+
+ b.Property("Genre")
+ .HasMaxLength(100)
+ .HasColumnType("character varying(100)")
+ .HasColumnName("genre");
+
+ b.Property("ImagePath")
+ .HasMaxLength(500)
+ .HasColumnType("character varying(500)")
+ .HasColumnName("image_path");
+
+ b.Property("IsDeleted")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("boolean")
+ .HasDefaultValue(false)
+ .HasColumnName("is_deleted");
+
+ b.Property("OriginalFileName")
+ .HasMaxLength(500)
+ .HasColumnType("character varying(500)")
+ .HasColumnName("original_file_name");
+
+ b.Property("ReleaseDate")
+ .HasColumnType("date")
+ .HasColumnName("release_date");
+
+ b.Property("TrackName")
+ .IsRequired()
+ .HasMaxLength(200)
+ .HasColumnType("character varying(200)")
+ .HasColumnName("track_name");
+
+ b.Property("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
+ }
+ }
+}
diff --git a/DeepDrftData/Migrations/20260607124422_AddOriginalFileName.cs b/DeepDrftData/Migrations/20260607124422_AddOriginalFileName.cs
new file mode 100644
index 0000000..7cf2da5
--- /dev/null
+++ b/DeepDrftData/Migrations/20260607124422_AddOriginalFileName.cs
@@ -0,0 +1,29 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace DeepDrftData.Migrations
+{
+ ///
+ public partial class AddOriginalFileName : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.AddColumn(
+ name: "original_file_name",
+ table: "track",
+ type: "character varying(500)",
+ maxLength: 500,
+ nullable: true);
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropColumn(
+ name: "original_file_name",
+ table: "track");
+ }
+ }
+}
diff --git a/DeepDrftData/Migrations/DeepDrftContextModelSnapshot.cs b/DeepDrftData/Migrations/DeepDrftContextModelSnapshot.cs
index ed99ec0..45cd361 100644
--- a/DeepDrftData/Migrations/DeepDrftContextModelSnapshot.cs
+++ b/DeepDrftData/Migrations/DeepDrftContextModelSnapshot.cs
@@ -72,6 +72,11 @@ namespace DeepDrftData.Migrations
.HasDefaultValue(false)
.HasColumnName("is_deleted");
+ b.Property("OriginalFileName")
+ .HasMaxLength(500)
+ .HasColumnType("character varying(500)")
+ .HasColumnName("original_file_name");
+
b.Property("ReleaseDate")
.HasColumnType("date")
.HasColumnName("release_date");
diff --git a/DeepDrftData/TrackConverter.cs b/DeepDrftData/TrackConverter.cs
index 30e7173..b8d2172 100644
--- a/DeepDrftData/TrackConverter.cs
+++ b/DeepDrftData/TrackConverter.cs
@@ -24,7 +24,8 @@ public class TrackConverter : IEntityToModelConverter
Genre = entity.Genre,
ReleaseDate = entity.ReleaseDate,
ImagePath = entity.ImagePath,
- CreatedByUserId = entity.CreatedByUserId
+ CreatedByUserId = entity.CreatedByUserId,
+ OriginalFileName = entity.OriginalFileName
};
public static TrackEntity Convert(TrackDto model) => new()
@@ -39,6 +40,7 @@ public class TrackConverter : IEntityToModelConverter
Genre = model.Genre,
ReleaseDate = model.ReleaseDate,
ImagePath = model.ImagePath,
- CreatedByUserId = model.CreatedByUserId
+ CreatedByUserId = model.CreatedByUserId,
+ OriginalFileName = model.OriginalFileName
};
}
diff --git a/DeepDrftManager/Components/Pages/Tracks/TrackList.razor b/DeepDrftManager/Components/Pages/Tracks/TrackList.razor
index fdee66d..aacde5e 100644
--- a/DeepDrftManager/Components/Pages/Tracks/TrackList.razor
+++ b/DeepDrftManager/Components/Pages/Tracks/TrackList.razor
@@ -47,6 +47,7 @@
Genre
Release Date
Entry Key
+ File Name
Actions
@@ -56,6 +57,7 @@
@(context.Genre ?? "—")
@(context.ReleaseDate?.ToString("yyyy-MM-dd") ?? "—")
@context.EntryKey
+ @(context.OriginalFileName ?? "—")
Id. A vault-without-SQL
/// orphan is handled and logged server-side; here it surfaces as a failed result.
+ /// is the browser's filename, captured at upload time and
+ /// stored as metadata; it is not user-editable afterwards.
///
Task> UploadTrackAsync(
Stream wavStream,
@@ -25,6 +27,7 @@ public interface ICmsTrackService
string? album,
string? genre,
string? releaseDate,
+ string? originalFileName,
long createdByUserId,
CancellationToken ct = default);
diff --git a/DeepDrftModels/DTOs/TrackDto.cs b/DeepDrftModels/DTOs/TrackDto.cs
index c368262..6b499db 100644
--- a/DeepDrftModels/DTOs/TrackDto.cs
+++ b/DeepDrftModels/DTOs/TrackDto.cs
@@ -18,4 +18,5 @@ public class TrackDto : BaseModel
public DateOnly? ReleaseDate { get; set; }
public string? ImagePath { get; set; }
public long? CreatedByUserId { get; set; }
+ public string? OriginalFileName { get; set; }
}
diff --git a/DeepDrftModels/Entities/TrackEntity.cs b/DeepDrftModels/Entities/TrackEntity.cs
index 28d8b14..688c22e 100644
--- a/DeepDrftModels/Entities/TrackEntity.cs
+++ b/DeepDrftModels/Entities/TrackEntity.cs
@@ -15,4 +15,5 @@ public class TrackEntity : BaseEntity, IEntity
public DateOnly? ReleaseDate { get; set; }
public string? ImagePath { get; set; }
public long? CreatedByUserId { get; set; }
+ public string? OriginalFileName { get; set; }
}