From 8c54a120d10faabeee30b7b0940602a647a28db9 Mon Sep 17 00:00:00 2001 From: florpan Date: Sat, 6 Sep 2025 16:53:23 +0200 Subject: [PATCH] confighantering. connection t postgres. test av import --- .gitignore | 1 + Frontend/src/styles/styles.css | 7 + Server/Bibblan.csproj | 9 + Server/Business/Services/CalibreService.cs | 8 +- Server/Controllers/CalibreController.cs | 282 +++++++++++++++++- Server/Models/BibblanOptions.cs | 1 + ...ibreContext.cs => SqliteCalibreContext.cs} | 38 ++- Server/Program.cs | 14 +- Server/appsettings.json | 3 +- 9 files changed, 341 insertions(+), 22 deletions(-) rename Server/Models/{CalibreContext.cs => SqliteCalibreContext.cs} (96%) diff --git a/.gitignore b/.gitignore index 67de48d..cee1aa6 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ Server/.vs Server/bin Server/obj Server/Bibblan.csproj.user +Server/appsettings.user.json diff --git a/Frontend/src/styles/styles.css b/Frontend/src/styles/styles.css index 01f9f68..eb998e9 100644 --- a/Frontend/src/styles/styles.css +++ b/Frontend/src/styles/styles.css @@ -1 +1,8 @@ @import "../../node_modules/bootstrap/scss/bootstrap.scss"; + +.book-card { + .card-img-top { + padding: 1rem; + aspect-ratio: 3 / 4; + } +} diff --git a/Server/Bibblan.csproj b/Server/Bibblan.csproj index 3fa154e..43fae32 100644 --- a/Server/Bibblan.csproj +++ b/Server/Bibblan.csproj @@ -16,6 +16,15 @@ + + + + + + PreserveNewest + true + PreserveNewest + diff --git a/Server/Business/Services/CalibreService.cs b/Server/Business/Services/CalibreService.cs index 222a62b..8063917 100644 --- a/Server/Business/Services/CalibreService.cs +++ b/Server/Business/Services/CalibreService.cs @@ -3,12 +3,12 @@ using Bibblan.ViewModels; using Microsoft.Extensions.Options; namespace Bibblan.Business.Services -{ +{ public class CalibreService { private readonly BibblanOptions _options; - CalibreContext _context; - public CalibreService(CalibreContext context, IOptions options) + SqliteCalibreContext _context; + public CalibreService(SqliteCalibreContext context, IOptions options) { _options = options.Value; _context = context; @@ -43,7 +43,7 @@ namespace Bibblan.Business.Services Comments = comment.Text, Language = l.LangCode, Path = b.Path, - HasCover = b.HasCover == "1", + HasCover = b.HasCover,// == "1", Formats = (from d in _context.Data where d.Book == b.Id orderby d.Format select new DataVm { Id = d.Id, Format = d.Format, FileName = d.Name + "." + d.Format.ToLower() }).ToList(), SeriesName = s.Name, SeriesNumber = b.SeriesIndex diff --git a/Server/Controllers/CalibreController.cs b/Server/Controllers/CalibreController.cs index 73e3353..b9b86a8 100644 --- a/Server/Controllers/CalibreController.cs +++ b/Server/Controllers/CalibreController.cs @@ -1,6 +1,8 @@ using Bibblan.Business.Services; using Bibblan.Models; using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Storage; namespace Bibblan.Controllers { @@ -9,8 +11,13 @@ namespace Bibblan.Controllers public class CalibreController : ControllerBase { CalibreService _service; - public CalibreController(CalibreService service) { + PostgresCalibreContext _postgresContext; + SqliteCalibreContext _sqliteContext; + + public CalibreController(CalibreService service, SqliteCalibreContext sqliteContext, PostgresCalibreContext postgresContext) { _service = service; + _postgresContext = postgresContext; + _sqliteContext = sqliteContext; } [HttpGet("books")] @@ -27,5 +34,278 @@ namespace Bibblan.Controllers return File(bytes, "image/jpeg", true); } + [HttpGet("dump")] + public IActionResult Dump() + { + //var e = _postgresContext.Database.EnsureCreated(); + //var script = _postgresContext.Database.GenerateCreateScript(); + // _postgresContext.Database.ExecuteSqlRaw(script); + + var books = 1;// DumpBooks(); + var auhtors = 1;// DumpAuthors(); + var comments = 1;// DumpComments(); + var data = 1;// DumpData(); + var identifiers = 1;// DumpIdentifiers(); + var languages = 1;// DumpLanguages(); + var publishers = 1;// DumpPublishers(); + var ratings = 1;// DumpRatings(); + var series = 1;// DumpSeries(); + var tags = 1;// DumpTags(); + + var ba = 1;// Dumpa(_postgresContext, _sqliteContext.BooksAuthorsLink.OrderBy(x => x.Id), _postgresContext.BooksAuthorsLink); + var bl = 1;// Dumpa(_postgresContext, _sqliteContext.BooksLanguagesLink.OrderBy(x => x.Id), _postgresContext.BooksLanguagesLink); + var bp = 1;// Dumpa(_postgresContext, _sqliteContext.BooksPublishersLink.OrderBy(x => x.Id), _postgresContext.BooksPublishersLink); + var br = 1;// Dumpa(_postgresContext, _sqliteContext.BooksRatingsLink.OrderBy(x => x.Id), _postgresContext.BooksRatingsLink); + var bs = 1;// Dumpa(_postgresContext, _sqliteContext.BooksSeriesLink.OrderBy(x => x.Id), _postgresContext.BooksSeriesLink); + var bt = 1;// Dumpa(_postgresContext, _sqliteContext.BooksTagsLink.OrderBy(x => x.Id), _postgresContext.BooksTagsLink); + + return Ok(new + { + books, + auhtors, + comments, + data, + identifiers, + languages, + publishers, + ratings, + series, + tags, + links = new + { + ba, + bl, + bp, + br, + bs, + bt + } + }); + } + + private int Dumpa(DbContext toContext, IQueryable from, DbSet to) + where T : class + { + var current = 0; + int step = 100; + + var done = false; + while (!done) + { + var records = from.Skip(current).Take(step); + done = records.Count() == 0; + foreach (var record in records) + { + to.Add(record); + } + toContext.SaveChanges(); + current += step; + } + return current; + + } + + private int DumpBooks() { + var current = 0; + int step = 100; + + var done = false; + while (!done) + { + var books = _sqliteContext.Books.OrderBy(b => b.Id).Skip(current).Take(step); + done = books.Count() == 0; + foreach (var book in books) + { + _postgresContext.Books.Add(book); + } + _postgresContext.SaveChanges(); + current += step; + } + return current; + } + + private int DumpAuthors() + { + var current = 0; + int step = 100; + + var done = false; + while (!done) + { + var authors = _sqliteContext.Authors.OrderBy(b => b.Id).Skip(current).Take(step); + done = authors.Count() == 0; + foreach (var author in authors) + { + _postgresContext.Authors.Add(author); + } + _postgresContext.SaveChanges(); + current += step; + } + return current; + } + + private int DumpComments() + { + var current = 0; + int step = 100; + + var done = false; + while (!done) + { + var comments = _sqliteContext.Comments.OrderBy(b => b.Id).Skip(current).Take(step); + done = comments.Count() == 0; + foreach (var comment in comments) + { + _postgresContext.Comments.Add(comment); + } + _postgresContext.SaveChanges(); + current += step; + } + return current; + } + + private int DumpData() + { + var current = 0; + int step = 100; + + var done = false; + while (!done) + { + var data = _sqliteContext.Data.OrderBy(b => b.Id).Skip(current).Take(step); + done = data.Count() == 0; + foreach (var d in data) + { + _postgresContext.Data.Add(d); + } + _postgresContext.SaveChanges(); + current += step; + } + return current; + } + + private int DumpIdentifiers() + { + var current = 0; + int step = 100; + + var done = false; + while (!done) + { + var identifiers = _sqliteContext.Identifiers.OrderBy(b => b.Id).Skip(current).Take(step); + done = identifiers.Count() == 0; + foreach (var id in identifiers) + { + _postgresContext.Identifiers.Add(id); + } + _postgresContext.SaveChanges(); + current += step; + } + return current; + } + + private int DumpLanguages() + { + var current = 0; + int step = 100; + + var done = false; + while (!done) + { + var languages = _sqliteContext.Languages.OrderBy(b => b.Id).Skip(current).Take(step); + done = languages.Count() == 0; + foreach (var lang in languages) + { + _postgresContext.Languages.Add(lang); + } + _postgresContext.SaveChanges(); + current += step; + } + return current; + } + + private int DumpPublishers() + { + var current = 0; + int step = 100; + + var done = false; + while (!done) + { + var publishers = _sqliteContext.Publishers.OrderBy(b => b.Id).Skip(current).Take(step); + done = publishers.Count() == 0; + foreach (var pub in publishers) + { + if(pub.Sort == null) + { + pub.Sort = pub.Name; + } + _postgresContext.Publishers.Add(pub); + } + _postgresContext.SaveChanges(); + current += step; + } + return current; + } + + private int DumpRatings() + { + var current = 0; + int step = 100; + + var done = false; + while (!done) + { + var ratings = _sqliteContext.Ratings.OrderBy(b => b.Id).Skip(current).Take(step); + done = ratings.Count() == 0; + foreach (var rating in ratings) + { + _postgresContext.Ratings.Add(rating); + } + _postgresContext.SaveChanges(); + current += step; + } + return current; + } + + private int DumpSeries() + { + var current = 0; + int step = 100; + + var done = false; + while (!done) + { + var series = _sqliteContext.Series.OrderBy(b => b.Id).Skip(current).Take(step); + done = series.Count() == 0; + foreach (var ser in series) + { + _postgresContext.Series.Add(ser); + } + _postgresContext.SaveChanges(); + current += step; + } + return current; + } + + private int DumpTags() + { + var current = 0; + int step = 100; + + var done = false; + while (!done) + { + var tags = _sqliteContext.Tags.OrderBy(b => b.Id).Skip(current).Take(step); + done = tags.Count() == 0; + foreach (var tag in tags) + { + _postgresContext.Tags.Add(tag); + } + _postgresContext.SaveChanges(); + current += step; + } + return current; + } } } diff --git a/Server/Models/BibblanOptions.cs b/Server/Models/BibblanOptions.cs index cbf7340..aab21f3 100644 --- a/Server/Models/BibblanOptions.cs +++ b/Server/Models/BibblanOptions.cs @@ -6,5 +6,6 @@ public string CalibreDb { get; set; } = String.Empty; public string CalibreRoot { get; set; } = String.Empty; + public string BibblanConnection { get; set; } = String.Empty; } } diff --git a/Server/Models/CalibreContext.cs b/Server/Models/SqliteCalibreContext.cs similarity index 96% rename from Server/Models/CalibreContext.cs rename to Server/Models/SqliteCalibreContext.cs index e9d07c2..e870276 100644 --- a/Server/Models/CalibreContext.cs +++ b/Server/Models/SqliteCalibreContext.cs @@ -15,8 +15,8 @@ namespace Bibblan.Models public long Id { get; set; } public string Title { get; set; } public string Sort { get; set; } - public string Timestamp { get; set; } - public string Pubdate { get; set; } + public DateTime Timestamp { get; set; } + public DateTime Pubdate { get; set; } public double SeriesIndex { get; set; } public string AuthorSort { get; set; } public string Isbn { get; set; } @@ -24,8 +24,8 @@ namespace Bibblan.Models public string Path { get; set; } public long Flags { get; set; } public string Uuid { get; set; } - public string HasCover { get; set; } - public string LastModified { get; set; } + public bool HasCover { get; set; } + public DateTime LastModified { get; set; } } public partial class BooksAuthorsLink @@ -101,11 +101,11 @@ namespace Bibblan.Models public string Label { get; set; } public string Name { get; set; } public string Datatype { get; set; } - public string MarkForDelete { get; set; } - public string Editable { get; set; } + public bool MarkForDelete { get; set; } + public bool Editable { get; set; } public string Display { get; set; } - public string IsMultiple { get; set; } - public string Normalized { get; set; } + public bool IsMultiple { get; set; } + public bool Normalized { get; set; } } public partial class Data @@ -161,7 +161,7 @@ namespace Bibblan.Models { public long Id { get; set; } public string Name { get; set; } - public string Sort { get; set; } + public string? Sort { get; set; } } public partial class Ratings @@ -183,7 +183,7 @@ namespace Bibblan.Models public string Name { get; set; } } - public partial class CalibreContext : DbContext + public partial class BaseContext : DbContext { public virtual DbSet Authors { get; set; } public virtual DbSet Books { get; set; } @@ -209,7 +209,7 @@ namespace Bibblan.Models public virtual DbSet Series { get; set; } public virtual DbSet Tags { get; set; } - public CalibreContext(DbContextOptions options) : base(options) + public BaseContext(DbContextOptions options) : base(options) { } @@ -762,4 +762,20 @@ namespace Bibblan.Models }); } } + + + public partial class SqliteCalibreContext : BaseContext + { + public SqliteCalibreContext(DbContextOptions options) : base(options) + { + } + } + + public partial class PostgresCalibreContext : BaseContext + { + public PostgresCalibreContext(DbContextOptions options) : base(options) + { + } + } + } diff --git a/Server/Program.cs b/Server/Program.cs index 495c97e..a782f2a 100644 --- a/Server/Program.cs +++ b/Server/Program.cs @@ -1,12 +1,16 @@ using Bibblan.Business.Services; using Bibblan.Models; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Options; var builder = WebApplication.CreateBuilder(args); +builder.Configuration.AddJsonFile($"appsettings.user.json", true, true); +var configSection = builder.Configuration.GetSection(BibblanOptions.Bibblan); +BibblanOptions config = new(); +configSection.Bind(config); // Add services to the container. -builder.Services.Configure( - builder.Configuration.GetSection(BibblanOptions.Bibblan)); +builder.Services.Configure(configSection); builder.Services.AddScoped(); @@ -16,9 +20,9 @@ builder.Services.AddControllers(); builder.Services.AddOpenApi(); -var db = "metadata.db"; -var connection = $"Data Source={db};Mode=ReadOnly;"; -builder.Services.AddDbContext(options => options.UseSqlite(connection)); +builder.Services.AddDbContext(options => options.UseSqlite($"Data Source={config.CalibreDb};Mode=ReadOnly;")); +builder.Services.AddDbContext(options => options.UseNpgsql(config.BibblanConnection)); + var app = builder.Build(); diff --git a/Server/appsettings.json b/Server/appsettings.json index 57d6d48..7b38c6f 100644 --- a/Server/appsettings.json +++ b/Server/appsettings.json @@ -8,6 +8,7 @@ "AllowedHosts": "*", "Bibblan": { "CalibreDb": "metadata.db", - "CalibreRoot": "\\\\diskstation\\Books\\" + "CalibreRoot": "c:\\my_books\\", + "BibblanConnection": "Server=localhost;Port=5432;Database=bibblan;User Id=bibblanuser;Password=1234567;" } }