Files
ReifenSpaeth/Lagerbestand/Models/KanbanTaskAttachment.cs
T

97 lines
2.6 KiB
C#

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Lagerbestand.Models;
/// <summary>
/// Represents a file attachment on a Kanban task
/// </summary>
public class KanbanTaskAttachment
{
public Guid Id { get; set; } = Guid.NewGuid();
public Guid TaskId { get; set; }
[Required]
[MaxLength(255)]
public string FileName { get; set; } = string.Empty;
[Required]
[MaxLength(100)]
public string ContentType { get; set; } = "application/octet-stream";
/// <summary>
/// File size in bytes
/// </summary>
public long FileSize { get; set; }
/// <summary>
/// Relative path to the file in the storage system (NFS/disk)
/// </summary>
[MaxLength(500)]
public string? FilePath { get; set; }
/// <summary>
/// Legacy: File content stored as binary (being migrated to file-based storage)
/// </summary>
[Obsolete("Use FilePath instead. This property is retained for migration purposes only.")]
public byte[]? FileContent { get; set; }
/// <summary>
/// User who uploaded the file
/// </summary>
public Guid? UploadedByUserId { get; set; }
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
// Navigation properties
public virtual KanbanTask? Task { get; set; }
public virtual AppUser? UploadedByUser { get; set; }
// Computed properties
[NotMapped]
public string FileSizeDisplay
{
get
{
if (FileSize < 1024) return $"{FileSize} B";
if (FileSize < 1024 * 1024) return $"{FileSize / 1024.0:F1} KB";
return $"{FileSize / (1024.0 * 1024.0):F1} MB";
}
}
[NotMapped]
public string FileIcon
{
get
{
var ext = Path.GetExtension(FileName).ToLowerInvariant();
return ext switch
{
".pdf" => "📄",
".doc" or ".docx" => "📝",
".xls" or ".xlsx" => "📊",
".ppt" or ".pptx" => "📽️",
".jpg" or ".jpeg" or ".png" or ".gif" or ".webp" => "🖼️",
".zip" or ".rar" or ".7z" => "📦",
".txt" => "📃",
_ => "📎"
};
}
}
[NotMapped]
public bool IsImage => ContentType.StartsWith("image/");
/// <summary>
/// Whether the file is stored on disk (vs legacy database storage)
/// </summary>
[NotMapped]
public bool IsFileBasedStorage => !string.IsNullOrEmpty(FilePath);
/// <summary>
/// Maximum file size allowed (10 MB)
/// </summary>
public const long MaxFileSize = 10 * 1024 * 1024;
}