feat(admin): standalone Projects page + per-project asset manager
Build backend images / build content-svc (push) Failing after 1m36s
Build backend images / build file-svc (push) Failing after 1m28s
Build backend images / build gateway (push) Failing after 2m11s
Build backend images / build identity-svc (push) Failing after 2m11s
Build backend images / build notification-svc (push) Failing after 3m46s
Build backend images / build render-svc (push) Failing after 55s
Build backend images / build studio-svc (push) Failing after 1m2s

- content-svc: GET /v1/projects (browse/search all projects across containers,
  paginated, admin) returning template name/slug + AE status; project_assets
  table (mig 23) + entity; GET/POST/DELETE /v1/projects/{id}/assets
- /admin/projects: searchable, paginated list of every renderable project with
  thumbnail, template, aspect/resolution, AE-file + publish status
- ProjectAssets component: list/upload/delete named footage/image/audio/font
  files per project (reused in the projects page; AE file upload alongside)
- nav + fa/en "Projects" label

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-03 00:39:33 +03:30
parent c4839bd35f
commit 7fe5f8a563
13 changed files with 364 additions and 2 deletions
@@ -19,6 +19,7 @@ public class ContentDbContext(DbContextOptions<ContentDbContext> options) : DbCo
public DbSet<ContainerCategory> ContainerCategories => Set<ContainerCategory>();
public DbSet<ContainerTag> ContainerTags => Set<ContainerTag>();
public DbSet<Project> Projects => Set<Project>();
public DbSet<ProjectAsset> ProjectAssets => Set<ProjectAsset>();
// Scenes
public DbSet<Scene> Scenes => Set<Scene>();
@@ -203,6 +204,21 @@ public class ContentDbContext(DbContextOptions<ContentDbContext> options) : DbCo
e.Property(x => x.SizeBytes).HasColumnName("size_bytes");
e.Property(x => x.CreatedAt).HasColumnName("created_at");
});
mb.Entity<ProjectAsset>(e =>
{
e.ToTable("project_assets");
e.HasKey(x => x.Id);
e.Property(x => x.Id).HasColumnName("id");
e.Property(x => x.ProjectId).HasColumnName("project_id");
e.Property(x => x.Name).HasColumnName("name").IsRequired();
e.Property(x => x.Kind).HasColumnName("kind").IsRequired();
e.Property(x => x.Url).HasColumnName("url").IsRequired();
e.Property(x => x.MinioKey).HasColumnName("minio_key");
e.Property(x => x.SizeBytes).HasColumnName("size_bytes");
e.Property(x => x.Sort).HasColumnName("sort");
e.Property(x => x.CreatedAt).HasColumnName("created_at");
});
}
private static void ConfigureTemplates(ModelBuilder mb)