feat: ship agent-first mission control v0.2.57
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Nexus.Api.DTOs;
|
||||
using Nexus.Api.Models;
|
||||
using Nexus.Api.Services;
|
||||
|
||||
namespace Nexus.Api.Controllers;
|
||||
@@ -11,42 +12,110 @@ namespace Nexus.Api.Controllers;
|
||||
public class ProjectsController(IProjectService projectService) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
public async Task<IResult> GetAll(CancellationToken ct)
|
||||
=> Results.Ok(await projectService.GetAllAsync(ct));
|
||||
[ProducesResponseType(typeof(IReadOnlyList<ProjectDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<IReadOnlyList<ProjectDto>>> GetAll(CancellationToken ct)
|
||||
=> Ok((await projectService.GetAllAsync(ct)).Select(project => Map(project)).ToArray());
|
||||
|
||||
[HttpGet("{id:guid}")]
|
||||
public async Task<IResult> GetById(Guid id, CancellationToken ct)
|
||||
[ProducesResponseType(typeof(ProjectDto), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
|
||||
public async Task<ActionResult<ProjectDto>> GetById(Guid id, CancellationToken ct)
|
||||
{
|
||||
var project = await projectService.GetByIdAsync(id, ct);
|
||||
return project is null ? Results.NotFound() : Results.Ok(project);
|
||||
return project is null ? NotFound() : Ok(Map(project));
|
||||
}
|
||||
|
||||
[HttpGet("{id:guid}/tasks")]
|
||||
[ProducesResponseType(typeof(IReadOnlyList<ProjectTaskDto>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
|
||||
public async Task<ActionResult<IReadOnlyList<ProjectTaskDto>>> GetTasks(
|
||||
Guid id,
|
||||
CancellationToken ct)
|
||||
{
|
||||
if (await projectService.GetByIdAsync(id, ct) is null)
|
||||
return NotFound();
|
||||
|
||||
var tasks = await projectService.GetTasksAsync(id, ct);
|
||||
return Ok(tasks.Select(task => new ProjectTaskDto(
|
||||
task.Id,
|
||||
task.Title,
|
||||
task.State,
|
||||
task.Priority,
|
||||
id,
|
||||
task.AssignedTo,
|
||||
task.ExpectedFrom,
|
||||
task.IsAgentTask,
|
||||
task.UpdatedAt)).ToArray());
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IResult> Create([FromBody] CreateProjectRequest request, CancellationToken ct)
|
||||
[ProducesResponseType(typeof(ProjectDto), StatusCodes.Status201Created)]
|
||||
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
|
||||
public async Task<ActionResult<ProjectDto>> Create(
|
||||
[FromBody] CreateProjectRequest request,
|
||||
CancellationToken ct)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(request.Name))
|
||||
return Results.ValidationProblem(new Dictionary<string, string[]> { ["name"] = ["Name is required."] });
|
||||
{
|
||||
ModelState.AddModelError("name", "Name is required.");
|
||||
return ValidationProblem(ModelState);
|
||||
}
|
||||
|
||||
var project = await projectService.CreateAsync(request, ct);
|
||||
return Results.Created($"/api/v1/projects/{project.Id}", project);
|
||||
return Created(
|
||||
$"/api/v1/projects/{project.Id}",
|
||||
Map(project, ProjectOperation(project, "created")));
|
||||
}
|
||||
|
||||
[HttpPatch("{id:guid}")]
|
||||
public async Task<IResult> Update(Guid id, [FromBody] UpdateProjectRequest request, CancellationToken ct)
|
||||
[ProducesResponseType(typeof(ProjectDto), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
|
||||
public async Task<ActionResult<ProjectDto>> Update(
|
||||
Guid id,
|
||||
[FromBody] UpdateProjectRequest request,
|
||||
CancellationToken ct)
|
||||
{
|
||||
var project = await projectService.UpdateAsync(id, request, ct);
|
||||
return project is null ? Results.NotFound() : Results.Ok(project);
|
||||
return project is null
|
||||
? NotFound()
|
||||
: Ok(Map(project, ProjectOperation(project, "updated")));
|
||||
}
|
||||
|
||||
[HttpDelete("{id:guid}")]
|
||||
public async Task<IResult> Delete(Guid id, CancellationToken ct)
|
||||
[ProducesResponseType(typeof(ProjectDto), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
|
||||
public async Task<IActionResult> Delete(Guid id, CancellationToken ct)
|
||||
{
|
||||
var result = await projectService.DeleteAsync(id, ct);
|
||||
return result.Outcome switch
|
||||
{
|
||||
ProjectDeleteOutcome.NotFound => Results.NotFound(),
|
||||
ProjectDeleteOutcome.Archived => Results.Ok(result.Project),
|
||||
_ => Results.NoContent()
|
||||
ProjectDeleteOutcome.NotFound => NotFound(),
|
||||
ProjectDeleteOutcome.Archived => Ok(Map(
|
||||
result.Project!,
|
||||
ProjectOperation(result.Project!, "archived"))),
|
||||
_ => Ok(Map(
|
||||
result.Project!,
|
||||
ProjectOperation(result.Project!, "deleted")))
|
||||
};
|
||||
}
|
||||
|
||||
private OperationResultDto ProjectOperation(
|
||||
Nexus.Api.Data.Project project,
|
||||
string status)
|
||||
=> OperationResultFactory.FromHttpContext(
|
||||
HttpContext,
|
||||
status,
|
||||
new EntityRefDto("project", project.Id.ToString(), project.Name));
|
||||
|
||||
private static ProjectDto Map(
|
||||
Nexus.Api.Data.Project project,
|
||||
OperationResultDto? operation = null)
|
||||
=> new(
|
||||
project.Id,
|
||||
project.Name,
|
||||
project.Description,
|
||||
project.Status.ToString(),
|
||||
project.Progress,
|
||||
project.UpdatedAt,
|
||||
operation);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user