book list api
This commit is contained in:
parent
2651e603c4
commit
b8c45ed93c
@ -59,6 +59,50 @@ namespace RMuseum.Controllers
|
|||||||
return Ok(poets);
|
return Ok(poets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// get list of books (GanjoorCat entries whose CatType is Book, sorted alphabetically by name),
|
||||||
|
/// optionally filtered by (part of) name and/or poet id. Not to be confused with
|
||||||
|
/// GetBooksAsync()/"books" above, which lists GanjoorCat entries by their (separate,
|
||||||
|
/// legacy) BookName field for cover-image generation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">optional, only books whose name contains this</param>
|
||||||
|
/// <param name="poetId">optional, only books belonging to this poet</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet]
|
||||||
|
[Route("book-catalog")]
|
||||||
|
[AllowAnonymous]
|
||||||
|
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(GanjoorBookViewModel[]))]
|
||||||
|
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
|
||||||
|
public async Task<IActionResult> GetBookCatalog(string name = null, int? poetId = null)
|
||||||
|
{
|
||||||
|
// only the common, unfiltered call (the one the home page's book search will use to load
|
||||||
|
// the full list once and filter client-side) is worth caching - a filtered call is cheap
|
||||||
|
// on a table this small (well under 200 rows) and caching every name/poetId combination
|
||||||
|
// would just grow the cache for no benefit.
|
||||||
|
if (string.IsNullOrEmpty(name) && poetId == null)
|
||||||
|
{
|
||||||
|
var cacheKey = $"ganjoor/book-catalog";
|
||||||
|
if (!_memoryCache.TryGetValue(cacheKey, out GanjoorBookViewModel[] cachedBooks))
|
||||||
|
{
|
||||||
|
RServiceResult<GanjoorBookViewModel[]> cachedRes =
|
||||||
|
await _ganjoorService.GetBookCatalogAsync();
|
||||||
|
if (!string.IsNullOrEmpty(cachedRes.ExceptionString))
|
||||||
|
return BadRequest(cachedRes.ExceptionString);
|
||||||
|
|
||||||
|
cachedBooks = cachedRes.Result;
|
||||||
|
if (AggressiveCacheEnabled)
|
||||||
|
_memoryCache.Set(cacheKey, cachedBooks, TimeSpan.FromHours(1));
|
||||||
|
}
|
||||||
|
return Ok(cachedBooks);
|
||||||
|
}
|
||||||
|
|
||||||
|
RServiceResult<GanjoorBookViewModel[]> res =
|
||||||
|
await _ganjoorService.GetBookCatalogAsync(name, poetId);
|
||||||
|
if (!string.IsNullOrEmpty(res.ExceptionString))
|
||||||
|
return BadRequest(res.ExceptionString);
|
||||||
|
return Ok(res.Result);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// gets list of poets grouped by centuries (first one is the pinned ones)
|
/// gets list of poets grouped by centuries (first one is the pinned ones)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
39
RMuseum/Models/Ganjoor/ViewModels/GanjoorBookViewModel.cs
Normal file
39
RMuseum/Models/Ganjoor/ViewModels/GanjoorBookViewModel.cs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
namespace RMuseum.Models.Ganjoor.ViewModels
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A GanjoorCat whose CatType is Book - a minimal view model for listing/searching books
|
||||||
|
/// (e.g. the home page's book search box), not the full category details
|
||||||
|
/// </summary>
|
||||||
|
public class GanjoorBookViewModel
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// id (GanjoorCat.Id)
|
||||||
|
/// </summary>
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// book name (GanjoorCat.Title)
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// full url, sample: /hafez/ghazal
|
||||||
|
/// </summary>
|
||||||
|
public string FullUrl { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// poet id (GanjoorCat.PoetId)
|
||||||
|
/// </summary>
|
||||||
|
public int PoetId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// poet short name (GanjoorPoet.Nickname)
|
||||||
|
/// </summary>
|
||||||
|
public string PoetName { get; set; }
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1096,6 +1096,17 @@
|
|||||||
</summary>
|
</summary>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="M:RMuseum.Controllers.GanjoorController.GetBookCatalog(System.String,System.Nullable{System.Int32})">
|
||||||
|
<summary>
|
||||||
|
get list of books (GanjoorCat entries whose CatType is Book, sorted alphabetically by name),
|
||||||
|
optionally filtered by (part of) name and/or poet id. Not to be confused with
|
||||||
|
GetBooksAsync()/"books" above, which lists GanjoorCat entries by their (separate,
|
||||||
|
legacy) BookName field for cover-image generation.
|
||||||
|
</summary>
|
||||||
|
<param name="name">optional, only books whose name contains this</param>
|
||||||
|
<param name="poetId">optional, only books belonging to this poet</param>
|
||||||
|
<returns></returns>
|
||||||
|
</member>
|
||||||
<member name="M:RMuseum.Controllers.GanjoorController.GetCenturiesAsync">
|
<member name="M:RMuseum.Controllers.GanjoorController.GetCenturiesAsync">
|
||||||
<summary>
|
<summary>
|
||||||
gets list of poets grouped by centuries (first one is the pinned ones)
|
gets list of poets grouped by centuries (first one is the pinned ones)
|
||||||
@ -12578,6 +12589,37 @@
|
|||||||
simulate naming
|
simulate naming
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="T:RMuseum.Models.Ganjoor.ViewModels.GanjoorBookViewModel">
|
||||||
|
<summary>
|
||||||
|
A GanjoorCat whose CatType is Book - a minimal view model for listing/searching books
|
||||||
|
(e.g. the home page's book search box), not the full category details
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:RMuseum.Models.Ganjoor.ViewModels.GanjoorBookViewModel.Id">
|
||||||
|
<summary>
|
||||||
|
id (GanjoorCat.Id)
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:RMuseum.Models.Ganjoor.ViewModels.GanjoorBookViewModel.Name">
|
||||||
|
<summary>
|
||||||
|
book name (GanjoorCat.Title)
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:RMuseum.Models.Ganjoor.ViewModels.GanjoorBookViewModel.FullUrl">
|
||||||
|
<summary>
|
||||||
|
full url, sample: /hafez/ghazal
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:RMuseum.Models.Ganjoor.ViewModels.GanjoorBookViewModel.PoetId">
|
||||||
|
<summary>
|
||||||
|
poet id (GanjoorCat.PoetId)
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:RMuseum.Models.Ganjoor.ViewModels.GanjoorBookViewModel.PoetName">
|
||||||
|
<summary>
|
||||||
|
poet short name (GanjoorPoet.Nickname)
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
<member name="P:RMuseum.Models.Ganjoor.ViewModels.GanjoorCatCorrectionViewModel.Id">
|
<member name="P:RMuseum.Models.Ganjoor.ViewModels.GanjoorCatCorrectionViewModel.Id">
|
||||||
<summary>
|
<summary>
|
||||||
correct id
|
correct id
|
||||||
@ -18549,6 +18591,16 @@
|
|||||||
<param name="includeBio"></param>
|
<param name="includeBio"></param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="M:RMuseum.Services.IGanjoorService.GetBookCatalogAsync(System.String,System.Nullable{System.Int32})">
|
||||||
|
<summary>
|
||||||
|
Get list of books (GanjoorCat entries whose CatType is Book), sorted alphabetically by name.
|
||||||
|
Not to be confused with GetBooksAsync() below, which lists GanjoorCat entries by their
|
||||||
|
(separate, legacy) BookName field for cover-image generation.
|
||||||
|
</summary>
|
||||||
|
<param name="name">optional, only books whose name contains this (case-insensitive)</param>
|
||||||
|
<param name="poetId">optional, only books belonging to this poet</param>
|
||||||
|
<returns></returns>
|
||||||
|
</member>
|
||||||
<member name="M:RMuseum.Services.IGanjoorService.GetPoetById(System.Int32,System.Boolean)">
|
<member name="M:RMuseum.Services.IGanjoorService.GetPoetById(System.Int32,System.Boolean)">
|
||||||
<summary>
|
<summary>
|
||||||
get poet by id
|
get poet by id
|
||||||
@ -22286,6 +22338,9 @@
|
|||||||
<summary>
|
<summary>
|
||||||
IGanjoorService implementation
|
IGanjoorService implementation
|
||||||
</summary>
|
</summary>
|
||||||
|
<summary>
|
||||||
|
IGanjoorService implementation
|
||||||
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:RMuseum.Services.Implementation.GanjoorService.SwitchCoupletBookmark(System.Guid,System.Int32,System.Int32)">
|
<member name="M:RMuseum.Services.Implementation.GanjoorService.SwitchCoupletBookmark(System.Guid,System.Int32,System.Int32)">
|
||||||
<summary>
|
<summary>
|
||||||
@ -22366,6 +22421,16 @@
|
|||||||
<param name="q"></param>
|
<param name="q"></param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="M:RMuseum.Services.Implementation.GanjoorService.GetBookCatalogAsync(System.String,System.Nullable{System.Int32})">
|
||||||
|
<summary>
|
||||||
|
Get list of books (GanjoorCat entries whose CatType is Book), sorted alphabetically by name.
|
||||||
|
Not to be confused with GetBooksAsync() elsewhere in this class, which lists GanjoorCat
|
||||||
|
entries by their (separate, legacy) BookName field for cover-image generation.
|
||||||
|
</summary>
|
||||||
|
<param name="name">optional, only books whose name contains this (case-insensitive)</param>
|
||||||
|
<param name="poetId">optional, only books belonging to this poet</param>
|
||||||
|
<returns></returns>
|
||||||
|
</member>
|
||||||
<member name="M:RMuseum.Services.Implementation.GanjoorService.GetCategoryWordCountsAsync(System.Int32,System.String,RSecurityBackend.Models.Generic.PagingParameterModel)">
|
<member name="M:RMuseum.Services.Implementation.GanjoorService.GetCategoryWordCountsAsync(System.Int32,System.String,RSecurityBackend.Models.Generic.PagingParameterModel)">
|
||||||
<summary>
|
<summary>
|
||||||
category word counts
|
category word counts
|
||||||
|
|||||||
@ -22,6 +22,16 @@ namespace RMuseum.Services
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<RServiceResult<GanjoorPoetViewModel[]>> GetPoets(bool published, bool includeBio = true);
|
Task<RServiceResult<GanjoorPoetViewModel[]>> GetPoets(bool published, bool includeBio = true);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get list of books (GanjoorCat entries whose CatType is Book), sorted alphabetically by name.
|
||||||
|
/// Not to be confused with GetBooksAsync() below, which lists GanjoorCat entries by their
|
||||||
|
/// (separate, legacy) BookName field for cover-image generation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">optional, only books whose name contains this (case-insensitive)</param>
|
||||||
|
/// <param name="poetId">optional, only books belonging to this poet</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<RServiceResult<GanjoorBookViewModel[]>> GetBookCatalogAsync(string name = null, int? poetId = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// get poet by id
|
/// get poet by id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -0,0 +1,61 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using RMuseum.Models.Ganjoor;
|
||||||
|
using RMuseum.Models.Ganjoor.ViewModels;
|
||||||
|
using RSecurityBackend.Models.Generic;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace RMuseum.Services.Implementation
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// IGanjoorService implementation
|
||||||
|
/// </summary>
|
||||||
|
public partial class GanjoorService : IGanjoorService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Get list of books (GanjoorCat entries whose CatType is Book), sorted alphabetically by name.
|
||||||
|
/// Not to be confused with GetBooksAsync() elsewhere in this class, which lists GanjoorCat
|
||||||
|
/// entries by their (separate, legacy) BookName field for cover-image generation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">optional, only books whose name contains this (case-insensitive)</param>
|
||||||
|
/// <param name="poetId">optional, only books belonging to this poet</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<RServiceResult<GanjoorBookViewModel[]>> GetBookCatalogAsync(string name = null, int? poetId = null)
|
||||||
|
{
|
||||||
|
var query = _context.GanjoorCategories.AsNoTracking()
|
||||||
|
.Where(c => c.CatType == GanjoorCatType.Book);
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(name))
|
||||||
|
{
|
||||||
|
query = query.Where(c => c.Title.Contains(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (poetId != null)
|
||||||
|
{
|
||||||
|
query = query.Where(c => c.PoetId == poetId.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<GanjoorBookViewModel> books =
|
||||||
|
await query
|
||||||
|
.Select(c => new GanjoorBookViewModel()
|
||||||
|
{
|
||||||
|
Id = c.Id,
|
||||||
|
Name = c.Title,
|
||||||
|
FullUrl = c.FullUrl,
|
||||||
|
PoetId = c.PoetId,
|
||||||
|
PoetName = c.Poet.Nickname,
|
||||||
|
})
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
// the fa-IR comparer can't be translated to SQL, so sorting happens here in memory -
|
||||||
|
// the same approach GetPoets() above uses, fine for a list this small (< 200 rows)
|
||||||
|
StringComparer fa = StringComparer.Create(new CultureInfo("fa-IR"), true);
|
||||||
|
books.Sort((a, b) => fa.Compare(a.Name, b.Name));
|
||||||
|
|
||||||
|
return new RServiceResult<GanjoorBookViewModel[]>(books.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user