serier och taggar

This commit is contained in:
2025-09-11 01:26:06 +02:00
parent e23822b30c
commit f88c25f117
8 changed files with 242 additions and 1 deletions

View File

@@ -51,5 +51,59 @@ namespace Bibblan.Business.Services
return conn.Query<AuthorVm>(query).Take(count).ToList();
}
internal List<SeriesVm> GetSeries(int count, BookFilter? filter)
{
var query = @"select s.id as seriesid, s.name as seriesname, b.*, a.*
--b.id as bookid, b.title, b.pubdate, b.series_index,
--a.id as authorid, a.name as authorname
from series s
inner join books_series_link bsl on s.id = bsl.series
inner join books b on bsl.book = b.id
inner join books_authors_link bal on b.id = bal.book
inner join authors a on bal.author = a.id";
if (!String.IsNullOrWhiteSpace(filter?.Query))
{
filter.Query = filter.Query?.ToLowerInvariant().Trim() ?? "";
query += $" where lower(s.name) like '%{filter.Query}%'";
}
var conn = new NpgsqlConnection(settings.BibblanConnection);
var lookup = new Dictionary<long, SeriesVm>();
conn.Query<SeriesVm, Books, Authors, SeriesVm>(query, (s,b,a) =>
{
SeriesVm svm;
if (!lookup.TryGetValue(s.Id, out svm))
{
lookup.Add(s.Id, svm = s);
}
svm.Books.Add(new ListBook
{
AuthorId = a.Id,
AuthorName = a.Name,
Id = b.Id,
PubDate = b.Pubdate,
SeriesIndex = b.SeriesIndex,
Title = b.Title
});
return svm;
}, splitOn: "id").Take(count).ToList();
return lookup.Values.AsList();
}
internal List<Tag> GetTags(BookFilter? filter)
{
var query = @"select t.id, t.name, count(btl.*) as bookcount from tags t
inner join books_tags_link btl on t.id = btl.tag
group by t.id, t.name
order by bookcount desc";
if (!String.IsNullOrWhiteSpace(filter?.Query))
{
filter.Query = filter.Query.ToLowerInvariant();
query += $" having lower(name) like '%{filter.Query}%'";
}
var conn = new NpgsqlConnection(settings.BibblanConnection);
return conn.Query<Tag>(query).ToList();
}
}
}

View File

@@ -66,5 +66,28 @@ namespace Bibblan.Controllers
}
[HttpGet("series")]
public IActionResult GetSeries(string query = null)
{
BookFilter filter = query != null ? new BookFilter
{
Query = query
} : null;
var series = _db.GetSeries(100, filter).ToList();
return Ok(series);
}
[HttpGet("tags")]
public IActionResult GetTags(string query = null)
{
BookFilter filter = query != null ? new BookFilter
{
Query = query
} : null;
var tags = _db.GetTags(filter).ToList();
return Ok(tags);
}
}
}

View File

@@ -1,7 +1,10 @@
using Bibblan.Business.Services;
using Bibblan.Models;
using Bibblan.ViewModels;
using Dapper;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using System.ComponentModel.DataAnnotations.Schema;
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddJsonFile($"appsettings.user.json", true, true);
@@ -28,6 +31,15 @@ builder.Services.AddDbContext<PostgresCalibreContext>(options => options.UseNpgs
var app = builder.Build();
Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true;
Dapper.SqlMapper.SetTypeMap(
typeof(SeriesVm),
new CustomPropertyTypeMap(
typeof(SeriesVm),
(type, columnName) =>
type.GetProperties().FirstOrDefault(prop =>
prop.GetCustomAttributes(false)
.OfType<ColumnAttribute>()
.Any(attr => attr.Name == columnName))));
app.UseDefaultFiles();
app.MapStaticAssets();

View File

@@ -0,0 +1,32 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace Bibblan.ViewModels
{
public class Tag
{
public long Id { get; set; }
public string Name { get; set; }
public int BookCount { get; set; }
}
public class ListBook
{
public long Id { get; set; }
public string Title { get; set; }
public DateTime PubDate { get; set; }
public double SeriesIndex { get; set; }
public long AuthorId { get; set; }
public string AuthorName { get; set; }
}
public class SeriesVm
{
[Column("seriesid")]
public long Id { get; set; }
[Column("seriesname")]
public string Name { get; set; }
public List<ListBook> Books { get; set; } = new();
}
}