feat(admin): project (template-item) manager + After Effects file upload
Build backend images / build content-svc (push) Failing after 50s
Build backend images / build file-svc (push) Failing after 1m5s
Build backend images / build gateway (push) Failing after 3m13s
Build backend images / build identity-svc (push) Failing after 1m32s
Build backend images / build notification-svc (push) Failing after 5m7s
Build backend images / build render-svc (push) Failing after 1m2s
Build backend images / build studio-svc (push) Failing after 54s
Build backend images / build content-svc (push) Failing after 50s
Build backend images / build file-svc (push) Failing after 1m5s
Build backend images / build gateway (push) Failing after 3m13s
Build backend images / build identity-svc (push) Failing after 1m32s
Build backend images / build notification-svc (push) Failing after 5m7s
Build backend images / build render-svc (push) Failing after 1m2s
Build backend images / build studio-svc (push) Failing after 54s
The admin could edit a container but not manage its renderable projects or attach
AE files. Now, inside the template editor:
- add a new project/variant under the container (name, WxH, aspect, resolution,
duration, fps, choose-mode) → POST /v1/projects (maps via container_id)
- upload the After Effects file (.aep/.zip) per project → new PATCH
/v1/projects/{id}/aep (sets AepFileUrl/Minio/Md5/Size + RenderAepComp), with an
"AE ✓ / بدون فایل" status badge
- set the render composition name; delete a variant
- ProjectResponse now surfaces aep_file_url / aep_file_size_bytes / render_aep_comp
Additive only — the existing aspect/resolution variant editing is unchanged.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -310,9 +310,28 @@ public class TemplateService(ContentDbContext db)
|
||||
p.OriginalWidth, p.OriginalHeight, p.Aspect,
|
||||
p.ProjectDurationSec, p.MinDurationSec, p.MaxDurationSec,
|
||||
p.FreeFps, p.ChooseMode.ToString(), p.Resolution.ToString(),
|
||||
p.IsPublished, p.Sort
|
||||
p.IsPublished, p.Sort,
|
||||
p.AepFileUrl, p.AepFileSizeBytes, p.RenderAepComp
|
||||
);
|
||||
|
||||
/// <summary>Attach an uploaded After Effects file (and render composition) to a project.</summary>
|
||||
public async Task<ProjectDetailResponse> SetProjectAepAsync(Guid id, SetAepRequest req)
|
||||
{
|
||||
var project = await db.Projects.FirstOrDefaultAsync(p => p.Id == id && p.DeletedAt == null)
|
||||
?? throw new KeyNotFoundException($"Project {id} not found");
|
||||
if (req.AepFileUrl != null) project.AepFileUrl = req.AepFileUrl;
|
||||
if (req.AepMinioBucket != null) project.AepMinioBucket = req.AepMinioBucket;
|
||||
if (req.AepMinioKey != null) project.AepMinioKey = req.AepMinioKey;
|
||||
if (req.AepFileMd5 != null) project.AepFileMd5 = req.AepFileMd5;
|
||||
if (req.AepFileSizeBytes.HasValue) project.AepFileSizeBytes = req.AepFileSizeBytes;
|
||||
if (!string.IsNullOrWhiteSpace(req.RenderAepComp)) project.RenderAepComp = req.RenderAepComp;
|
||||
if (req.Folder != null) project.Folder = req.Folder;
|
||||
project.AepUploadedAt = DateTime.UtcNow;
|
||||
project.UpdatedAt = DateTime.UtcNow;
|
||||
await db.SaveChangesAsync();
|
||||
return await GetProjectDetailAsync(id);
|
||||
}
|
||||
|
||||
private static ProjectDetailResponse MapProjectDetail(Project p) => new(
|
||||
p.Id, p.ContainerId, p.Name, p.Description, p.Image, p.FullDemo, p.DemoScriptTag, p.DownloadLink,
|
||||
p.OriginalWidth, p.OriginalHeight, p.Aspect,
|
||||
|
||||
@@ -77,6 +77,12 @@ public class ProjectsController(TemplateService svc) : ControllerBase
|
||||
public async Task<IActionResult> PatchProject(Guid id, [FromBody] PatchProjectRequest req) =>
|
||||
Ok(await svc.PatchProjectAsync(id, req));
|
||||
|
||||
// Attach an uploaded After Effects file (.aep) + render composition to a project.
|
||||
[Authorize(Roles = "Admin")]
|
||||
[HttpPatch("{id:guid}/aep")]
|
||||
public async Task<IActionResult> SetAep(Guid id, [FromBody] SetAepRequest req) =>
|
||||
Ok(await svc.SetProjectAepAsync(id, req));
|
||||
|
||||
[Authorize(Roles = "Admin")]
|
||||
[HttpDelete("{id:guid}")]
|
||||
public async Task<IActionResult> DeleteProject(Guid id)
|
||||
|
||||
@@ -244,6 +244,16 @@ public record UpdateProjectRequest(
|
||||
|
||||
// Partial update — only non-null fields are applied, so editing an aspect/resolution
|
||||
// never wipes render/colour data that the full UpdateProjectRequest would require.
|
||||
public record SetAepRequest(
|
||||
string? AepFileUrl,
|
||||
string? AepMinioBucket,
|
||||
string? AepMinioKey,
|
||||
string? AepFileMd5,
|
||||
long? AepFileSizeBytes,
|
||||
string? RenderAepComp,
|
||||
string? Folder
|
||||
);
|
||||
|
||||
public record PatchProjectRequest(
|
||||
string? Name,
|
||||
string? Description,
|
||||
|
||||
@@ -128,7 +128,10 @@ public record ProjectResponse(
|
||||
string ChooseMode,
|
||||
string Resolution,
|
||||
bool IsPublished,
|
||||
int Sort
|
||||
int Sort,
|
||||
string? AepFileUrl,
|
||||
long? AepFileSizeBytes,
|
||||
string RenderAepComp
|
||||
);
|
||||
|
||||
public record ProjectDetailResponse(
|
||||
|
||||
Reference in New Issue
Block a user