using FlatRender.ContentSvc.Application.Services; using FlatRender.ContentSvc.Models.Requests; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace FlatRender.ContentSvc.Controllers; [ApiController] [Route("v1/templates")] public class TemplatesController(TemplateService svc) : ControllerBase { // ── Containers ──────────────────────────────────────────────────────────── [HttpGet] public async Task ListContainers([FromQuery] ContainerListRequest req) => Ok(await svc.GetContainersAsync(req)); [HttpGet("{slug}")] public async Task GetContainer(string slug) { await svc.IncrementContainerViewAsync( (await svc.GetContainerBySlugAsync(slug)).Id); return Ok(await svc.GetContainerBySlugAsync(slug)); } [Authorize(Roles = "Admin")] [HttpPost] public async Task CreateContainer([FromBody] CreateContainerRequest req) => Ok(await svc.CreateContainerAsync(req)); [Authorize(Roles = "Admin")] [HttpPut("{id:guid}")] public async Task UpdateContainer(Guid id, [FromBody] UpdateContainerRequest req) => Ok(await svc.UpdateContainerAsync(id, req)); [Authorize(Roles = "Admin")] [HttpDelete("{id:guid}")] public async Task DeleteContainer(Guid id) { await svc.DeleteContainerAsync(id); return NoContent(); } // ── Ranking: set manual sort weight (feature / pin) ───────────────────────── [Authorize(Roles = "Admin")] [HttpPatch("{id:guid}/sort")] public async Task SetSort(Guid id, [FromBody] SetSortRequest req) { await svc.SetContainerSortAsync(id, req.Sort); return Ok(new { ok = true }); } } public record SetSortRequest(int Sort); [ApiController] [Route("v1/projects")] public class ProjectsController(TemplateService svc) : ControllerBase { // Browse/search all projects across templates (admin). [Authorize(Roles = "Admin")] [HttpGet] public async Task List([FromQuery] string? q, [FromQuery] Guid? containerId, [FromQuery] int page = 1, [FromQuery] int pageSize = 30) => Ok(await svc.ListProjectsAsync(q, containerId, page, pageSize)); [HttpGet("{id:guid}")] public async Task GetProject(Guid id) => Ok(await svc.GetProjectDetailAsync(id)); // ── Per-project assets (footage / images / audio / fonts) ────────────────── [HttpGet("{id:guid}/assets")] public async Task ListAssets(Guid id) => Ok(await svc.ListAssetsAsync(id)); [Authorize(Roles = "Admin")] [HttpPost("{id:guid}/assets")] public async Task AddAsset(Guid id, [FromBody] CreateAssetRequest req) => Ok(await svc.AddAssetAsync(id, req)); [Authorize(Roles = "Admin")] [HttpDelete("{id:guid}/assets/{assetId:guid}")] public async Task DeleteAsset(Guid id, Guid assetId) { await svc.DeleteAssetAsync(assetId); return NoContent(); } [Authorize(Roles = "Admin")] [HttpPost] public async Task CreateProject([FromBody] CreateProjectRequest req) => Ok(await svc.CreateProjectAsync(req)); [Authorize(Roles = "Admin")] [HttpPut("{id:guid}")] public async Task UpdateProject(Guid id, [FromBody] UpdateProjectRequest req) => Ok(await svc.UpdateProjectAsync(id, req)); // Partial update (aspect / resolution / dimensions / duration) without wiping other fields. [Authorize(Roles = "Admin")] [HttpPatch("{id:guid}")] public async Task 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 SetAep(Guid id, [FromBody] SetAepRequest req) => Ok(await svc.SetProjectAepAsync(id, req)); [Authorize(Roles = "Admin")] [HttpDelete("{id:guid}")] public async Task DeleteProject(Guid id) { await svc.DeleteProjectAsync(id); return NoContent(); } }