feat(cv): redesign document editing with revision-safe letters and writing tools
This commit is contained in:
@@ -3,6 +3,7 @@ using JobTrackerApi.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace JobTrackerApi.Controllers;
|
||||
|
||||
@@ -19,18 +20,21 @@ namespace JobTrackerApi.Controllers;
|
||||
public sealed class ApplicationAssetsController : ControllerBase
|
||||
{
|
||||
public sealed record AttachVariantRequest(int? VariantId);
|
||||
public sealed record SaveCoverLetterRequest(string? Text, string? Source, string? AiAction, int? ExpectedVersion = null);
|
||||
public sealed record SaveCoverLetterRequest(string? Text, string? Source, string? AiAction, int? ExpectedVersion = null, CoverLetterDocumentSettings? DocumentSettings = null);
|
||||
public sealed record PreviewCoverLetterRequest(string? Text, CoverLetterDocumentSettings? DocumentSettings = null);
|
||||
public sealed record RestoreCoverLetterRequest(int? ExpectedVersion);
|
||||
|
||||
private readonly UserManager<ApplicationUser> _users;
|
||||
private readonly IApplicationAssetsService _assets;
|
||||
private readonly ISubmittedApplicationPackageService _packages;
|
||||
private readonly ICvPdfExporter? _pdf;
|
||||
|
||||
public ApplicationAssetsController(UserManager<ApplicationUser> users, IApplicationAssetsService assets, ISubmittedApplicationPackageService packages)
|
||||
public ApplicationAssetsController(UserManager<ApplicationUser> users, IApplicationAssetsService assets, ISubmittedApplicationPackageService packages, ICvPdfExporter? pdf = null)
|
||||
{
|
||||
_users = users;
|
||||
_assets = assets;
|
||||
_packages = packages;
|
||||
_pdf = pdf;
|
||||
}
|
||||
|
||||
[HttpGet("cv")]
|
||||
@@ -74,11 +78,41 @@ public sealed class ApplicationAssetsController : ControllerBase
|
||||
{
|
||||
var userId = await CurrentUserIdAsync();
|
||||
if (userId is null) return Unauthorized();
|
||||
if (request.DocumentSettings is { SchemaVersion: not 1 }) return BadRequest("Unsupported letter settings schema.");
|
||||
var result = await _assets.SaveCoverLetterAsync(
|
||||
userId, jobId, request?.Text, request?.Source ?? CoverLetterSources.Manual, request?.AiAction, request?.ExpectedVersion, ct);
|
||||
userId, jobId, request?.Text, request?.Source ?? CoverLetterSources.Manual, request?.AiAction, request?.ExpectedVersion, ct, request?.DocumentSettings);
|
||||
return result is null ? NotFound() : Ok(result);
|
||||
}
|
||||
|
||||
[HttpPost("cover-letter/preview")]
|
||||
public async Task<ActionResult<CoverLetterRenderDto>> PreviewCoverLetter(int jobId, [FromBody] PreviewCoverLetterRequest request, CancellationToken ct)
|
||||
{
|
||||
var userId = await CurrentUserIdAsync();
|
||||
if (userId is null) return Unauthorized();
|
||||
if (request.DocumentSettings is { SchemaVersion: not 1 }) return BadRequest("Unsupported letter settings schema.");
|
||||
var result = await _assets.PreviewCoverLetterAsync(userId, jobId, request.Text, request.DocumentSettings, ct);
|
||||
return result is null ? NotFound() : Ok(result);
|
||||
}
|
||||
|
||||
[HttpPost("cover-letter/export-pdf")]
|
||||
public async Task<IActionResult> ExportCoverLetterPdf(int jobId, CancellationToken ct, [FromQuery] int? expectedVersion = null)
|
||||
{
|
||||
var userId = await CurrentUserIdAsync();
|
||||
if (userId is null) return Unauthorized();
|
||||
try
|
||||
{
|
||||
var render = await _assets.RenderSavedCoverLetterAsync(userId, jobId, expectedVersion, ct);
|
||||
if (render is null) return NotFound();
|
||||
var artifact = await (_pdf ?? throw new InvalidOperationException("Letter PDF export is not configured."))
|
||||
.ExportAsync(userId, new TailoredCvRenderResult(render.ThemeId, render.SuggestedFileName, render.Html), ct);
|
||||
return File(artifact.Bytes, "application/pdf", artifact.FileName);
|
||||
}
|
||||
catch (DbUpdateConcurrencyException)
|
||||
{
|
||||
return Conflict(new { code = "revision_conflict", message = "The application changed. Save and review the current letter before exporting." });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("cover-letter/versions/{version:int}/restore")]
|
||||
public async Task<ActionResult<CoverLetterDto>> RestoreCoverLetter(int jobId, int version, [FromBody] RestoreCoverLetterRequest? request, CancellationToken ct)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user