Add success story add/edit and list (#4)

still a work in progress
This commit is contained in:
2021-01-21 23:05:27 -05:00
parent 340b93c6d7
commit 7f7eb191fb
15 changed files with 484 additions and 29 deletions

View File

@@ -33,6 +33,7 @@ namespace JobsJobsJobs.Server.Areas.Api.Controllers
/// Constructor
/// </summary>
/// <param name="db">The data context to use for this request</param>
/// <param name="clock">The clock instance to use for this request</param>
public ProfileController(JobsDbContext db, IClock clock)
{
_db = db;
@@ -114,5 +115,20 @@ namespace JobsJobsJobs.Server.Areas.Api.Controllers
[HttpGet("search")]
public async Task<IActionResult> Search([FromQuery] ProfileSearch search) =>
Ok(await _db.SearchProfiles(search));
[HttpPatch("employment-found")]
public async Task<IActionResult> EmploymentFound()
{
var profile = await _db.FindProfileByCitizen(CurrentCitizenId);
if (profile == null) return NotFound();
var updated = profile with { SeekingEmployment = false };
_db.Update(updated);
await _db.SaveChangesAsync();
return Ok();
}
}
}

View File

@@ -0,0 +1,79 @@
using JobsJobsJobs.Server.Data;
using JobsJobsJobs.Shared;
using JobsJobsJobs.Shared.Api;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using NodaTime;
using System.Security.Claims;
using System.Threading.Tasks;
namespace JobsJobsJobs.Server.Areas.Api.Controllers
{
/// <summary>
/// API controller for success stories
/// </summary>
[Route("api/[controller]")]
[Authorize]
[ApiController]
public class SuccessController : Controller
{
/// <summary>
/// The data context
/// </summary>
private readonly JobsDbContext _db;
/// <summary>
/// The NodaTime clock instance
/// </summary>
private readonly IClock _clock;
/// <summary>
/// Constructor
/// </summary>
/// <param name="db">The data context to use for this request</param>
/// <param name="clock">The clock instance to use for this request</param>
public SuccessController(JobsDbContext db, IClock clock)
{
_db = db;
_clock = clock;
}
/// <summary>
/// The current citizen ID
/// </summary>
private CitizenId CurrentCitizenId => CitizenId.Parse(User.FindFirst(ClaimTypes.NameIdentifier)!.Value);
[HttpGet("{id}")]
public async Task<IActionResult> Retrieve(string id) =>
Ok(await _db.FindSuccessById(SuccessId.Parse(id)));
[HttpPost("save")]
public async Task<IActionResult> Save([FromBody] StoryForm form)
{
if (form.Id == "new")
{
var story = new Success(await SuccessId.Create(), CurrentCitizenId, _clock.GetCurrentInstant(),
form.FromHere, string.IsNullOrWhiteSpace(form.Story) ? null : new MarkdownString(form.Story));
await _db.AddAsync(story);
}
else
{
var story = await _db.FindSuccessById(SuccessId.Parse(form.Id));
if (story == null) return NotFound();
var updated = story with
{
FromHere = form.FromHere,
Story = string.IsNullOrWhiteSpace(form.Story) ? null : new MarkdownString(form.Story)
};
_db.Update(updated);
}
await _db.SaveChangesAsync();
return Ok();
}
[HttpGet("list")]
public async Task<IActionResult> List() =>
Ok(await _db.AllStories());
}
}

View File

@@ -1,11 +1,9 @@
using JobsJobsJobs.Shared;
using JobsJobsJobs.Shared.Api;
using Microsoft.EntityFrameworkCore;
using Npgsql;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JobsJobsJobs.Server.Data

View File

@@ -0,0 +1,34 @@
using JobsJobsJobs.Shared;
using JobsJobsJobs.Shared.Api;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace JobsJobsJobs.Server.Data
{
/// <summary>
/// Extensions to JobsDbContext to support manipulation of success stories
/// </summary>
public static class SuccessExtensions
{
/// <summary>
/// Get a success story by its ID
/// </summary>
/// <param name="id">The ID of the story to retrieve</param>
/// <returns>The success story, if found</returns>
public static async Task<Success?> FindSuccessById(this JobsDbContext db, SuccessId id) =>
await db.Successes.AsNoTracking().SingleOrDefaultAsync(s => s.Id == id).ConfigureAwait(false);
/// <summary>
/// Get a list of success stories, with the information needed for the list page
/// </summary>
/// <returns>A list of success stories, citizen names, and dates</returns>
public static async Task<IEnumerable<StoryEntry>> AllStories(this JobsDbContext db) =>
await db.Successes
.Join(db.Citizens, s => s.CitizenId, c => c.Id, (s, c) => new { Success = s, Citizen = c })
.OrderByDescending(it => it.Success.RecordedOn)
.Select(it => new StoryEntry(it.Success.Id, it.Citizen.Id, it.Citizen.DisplayName, it.Success.RecordedOn))
.ToListAsync().ConfigureAwait(false);
}
}