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;"
}
}